Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>, Lists.newArrayList(externs, root), this);
}
private Map<String,Boolean> constantMap = Maps.newHashMap();
@Override
public void visit(NodeTraversal t, Node n, Node parent) {
if (n.getType() == Token.NAME) {
String name = n.getString();
if (n.getString().isEmpty()) {
return;
}
boolean isConst = n.getBooleanProp(Node.IS_CONSTANT_NAME);
if (checkUserDeclarations) {
boolean expectedConst = false;
if (NodeUtil.isConstantName(n)
|| compiler.getCodingConvention().isConstant(n.getString())) {
expectedConst = true;
} else {
expectedConst = false;
JSDocInfo info = null;
Var var = t.getScope().getVar(n.getString());
if (var != null) {
info = var.getJSDocInfo();
}
if (info != null && info.isConstant()) {
expectedConst = true;
} else {
expectedConst = false;
}
}
if (expectedConst) {
Preconditions.checkState(expectedConst == isConst,
"The name " + name + " is not annotated as constant.");
} else {
Preconditions.checkState(expectedConst == isConst,
"The name " + name + " should not be annotated as constant.");
}
}
Boolean value = constantMap.get(name);
if (value == null) {
constantMap.put(name, isConst);
} else {
Preconditions.checkState(value.booleanValue() == isConst,
"The name " + name + " is not consistently annotated as " +
"constant.");
}
}
}
}
/**
* Simplify the AST:
* - VAR declarations split, so they represent exactly one child
* declaration.
* - WHILEs are converted to FORs
* - FOR loop are initializers are moved out of the FOR structure
* - LABEL node of children other than LABEL, BLOCK, WHILE, FOR, or DO are
* moved into a block.
*/
static class NormalizeStatements implements Callback {
private final AbstractCompiler compiler;
private final boolean assertOnChange;
NormalizeStatements(AbstractCompiler compiler, boolean assertOnChange
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>) {
this.compiler = compiler;
this.assertOnChange = assertOnChange;
}
private void reportCodeChange(String changeDescription) {
if (assertOnChange) {
throw new IllegalStateException(
"Normalize constraints violated:\n" + changeDescription);
}
compiler.reportCodeChange();
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
doStatementNormalizations(t, n, parent);
return true;
}
@Override
public void visit(NodeTraversal t, Node n, Node parent) {
switch (n.getType()) {
case Token.WHILE:
if (CONVERT_WHILE_TO_FOR) {
Node expr = n.getFirstChild();
n.setType(Token.FOR);
n.addChildBefore(new Node(Token.EMPTY), expr);
n.addChildAfter(new Node(Token.EMPTY), expr);
reportCodeChange("WHILE node");
}
break;
}
}
/**
* Do normalizations that introduce new siblings or parents.
*/
private void doStatementNormalizations(
NodeTraversal t, Node n, Node parent) {
if (n.getType() == Token.LABEL) {
normalizeLabels(n);
}
// Only inspect the children of SCRIPTs, BLOCKs and LABELs, as all these
// are the only legal place for VARs and FOR statements.
if (NodeUtil.isStatementBlock(n) || n.getType() == Token.LABEL) {
extractForInitializer(n, null, null);
}
// Only inspect the children of SCRIPTs, BLOCKs, as all these
// are the only legal place for VARs.
if (NodeUtil.isStatementBlock(n)) {
splitVarDeclarations(n);
}
if (n.getType() == Token.FUNCTION) {
moveNamedFunctions(n.getLastChild());
}
}
// TODO(johnlenz): Move this to NodeTypeNormalizer once the unit tests are
// fixed.
/**
* Limit the number of special cases where LABELs need to be handled. Only
* BLOCK and loops are allowed to be labeled. Loop labels must remain in
* place as the named continues are not allowed for labeled blocks.
*/
private void normalizeLabels(Node n)
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS> {
Preconditions.checkArgument(n.getType() == Token.LABEL);
Node last = n.getLastChild();
switch (last.getType()) {
case Token.LABEL:
case Token.BLOCK:
case Token.FOR:
case Token.WHILE:
case Token.DO:
return;
default:
Node block = new Node(Token.BLOCK);
n.replaceChild(last, block);
block.addChildToFront(last);
reportCodeChange("LABEL normalization");
return;
}
}
/**
* Bring the initializers out of FOR loops. These need to be placed
* before any associated LABEL nodes. This needs to be done from the top
* level label first so this is called as a pre-order callback (from
* shouldTraverse).
*
* @param n The node to inspect.
* @param before The node to insert the initializer before.
* @param beforeParent The parent of the node before which the initializer
* will be inserted.
*/
private void extractForInitializer(
Node n, Node before, Node beforeParent) {
for (Node next, c = n.getFirstChild(); c != null; c = next) {
next = c.getNext();
Node insertBefore = (before == null) ? c : before;
Node insertBeforeParent = (before == null) ? n : beforeParent;
switch (c.getType()) {
case Token.LABEL:
extractForInitializer(c, insertBefore, insertBeforeParent);
break;
case Token.FOR:
if (!NodeUtil.isForIn(c)
&& c.getFirstChild().getType() != Token.EMPTY) {
Node init = c.getFirstChild();
c.replaceChild(init, new Node(Token.EMPTY));
Node newStatement;
// Only VAR statements, and expressions are allowed,
// but are handled differently.
if (init.getType() == Token.VAR) {
newStatement = init;
} else {
newStatement = NodeUtil.newExpr(init);
}
insertBeforeParent.addChildBefore(newStatement, insertBefore);
reportCodeChange("FOR initializer");
}
break;
}
}
}
/**
* Split a var node such as:
* var a, b;
* into individual statements:
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>
* var a;
* var b;
* @param n The whose children we should inspect.
*/
private void splitVarDeclarations(Node n) {
for (Node next, c = n.getFirstChild(); c != null; c = next) {
next = c.getNext();
if (c.getType() == Token.VAR) {
if (assertOnChange && !c.hasChildren()) {
throw new IllegalStateException("Empty VAR node.");
}
while (c.getFirstChild() != c.getLastChild()) {
Node name = c.getFirstChild();
c.removeChild(name);
Node newVar = new Node(
Token.VAR, name, n.getLineno(), n.getCharno());
n.addChildBefore(newVar, c);
reportCodeChange("VAR with multiple children");
}
}
}
}
/**
* Move all the functions that are valid at the execution of the first
* statement of the function to the beginning of the function definition.
*/
private void moveNamedFunctions(Node functionBody) {
Preconditions.checkState(
functionBody.getParent().getType() == Token.FUNCTION);
Node previous = null;
Node current = functionBody.getFirstChild();
// Skip any declarations at the beginning of the function body, they
// are already in the right place.
while (current != null && NodeUtil.isFunctionDeclaration(current)) {
previous = current;
current = current.getNext();
}
// Find any remaining declarations and move them.
Node insertAfter = previous;
while (current != null) {
// Save off the next node as the current node maybe removed.
Node next = current.getNext();
if (NodeUtil.isFunctionDeclaration(current)) {
// Remove the declaration from the body.
Preconditions.checkNotNull(previous);
functionBody.removeChildAfter(previous);
// Readd the function at the top of the function body (after any
// previous declarations).
insertAfter = addToFront(functionBody, current, insertAfter);
reportCodeChange("Move function declaration not at top of function");
} else {
// Update the previous only if the current node hasn't been moved.
previous = current;
}
current = next;
}
}
/**
* @param after The child node to insert the newChild after,
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>, as the next node of interest is the parent's
// next sibling.
//
if (n.hasChildren()) {
// The var is being initialize, preserve the new value.
parent.removeChild(n);
// Convert "var name = value" to "name = value"
Node value = n.getFirstChild();
n.removeChild(value);
Node replacement = new Node(Token.ASSIGN, n, value);
gramps.replaceChild(parent, new Node(Token.EXPR_RESULT, replacement));
} else {
// It is an empty reference remove it.
if (NodeUtil.isStatementBlock(gramps)) {
gramps.removeChild(parent);
} else if (gramps.getType() == Token.FOR) {
// This is the "for (var a in b)..." case. We don't need to worry
// about initializers in "for (var a;;)..." as those are moved out
// as part of the other normalizations.
parent.removeChild(n);
gramps.replaceChild(parent, n);
} else {
Preconditions.checkState(gramps.getType() == Token.LABEL);
gramps.replaceChild(parent, new Node(Token.EMPTY));
}
}
reportCodeChange("Duplicate VAR declaration");
}
}
}
/**
* A simple class that causes scope to be created.
*/
private final class ScopeTicklingCallback
implements NodeTraversal.ScopedCallback {
@Override
public void enterScope(NodeTraversal t) {
// Cause the scope to be created, which will cause duplicate
// to be found.
t.getScope();
}
@Override
public void exitScope(NodeTraversal t) {
// Nothing to do.
}
@Override
public boolean shouldTraverse(
NodeTraversal nodeTraversal, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node n, Node parent) {
// Nothing to do.
}
}
}
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>name);
}
nameStack.push(renamer);
}
break;
case Token.CATCH:
{
Renamer renamer = nameStack.peek().forChildScope();
String name = n.getFirstChild().getString();
renamer.addDeclaredName(name);
nameStack.push(renamer);
}
break;
}
return true;
}
@Override
public void visit(NodeTraversal t, Node n, Node parent) {
switch (n.getType()) {
case Token.NAME:
String newName = getReplacementName(n.getString());
if (newName != null) {
Renamer renamer = nameStack.peek();
if (renamer.stripConstIfReplaced()) {
// TODO(johnlenz): Do we need to do anything about the javadoc?
n.removeProp(Node.IS_CONSTANT_NAME);
}
n.setString(newName);
t.getCompiler().reportCodeChange();
}
break;
case Token.FUNCTION:
// Remove function recursive name (if any).
nameStack.pop();
break;
case Token.CATCH:
// Remove catch except name from the stack of names.
nameStack.pop();
break;
}
}
/**
* Walks the stack of name maps and finds the replacement name for the
* current scope.
*/
private String getReplacementName(String oldName) {
for (Renamer names : nameStack) {
String newName = names.getReplacementName(oldName);
if (newName != null) {
return newName;
}
}
return null;
}
/**
* Traverses the current scope and collects declared names. Does not
* decent into functions or add CATCH exceptions.
*/
private void findDeclaredNames(Node n, Node parent, Renamer renamer) {
// Do a shallow traversal, so don't traverse into function declarations,
// except for the name of the function itself.
if (parent == null
|| parent.getType() != Token.FUNCTION
|| n == parent.getFirstChild()) {
if (NodeUtil.isVarDeclaration(n)) {
renamer.addDeclaredName(n.getString());
} else if (NodeUtil.isFunctionDeclaration(n)) {
Node name
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>/*
* Copyright 2004 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import com.google.common.collect.Maps;
import com.google.javascript.rhino.FunctionNode;
import com.google.javascript.rhino.JSDocInfo;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* NodeUtil contains utilities that get properties from the Node object.
*
*
*
*/
public final class NodeUtil {
// TODO(user): Eliminate this class and make all of the static methods
// instance methods of com.google.javascript.rhino.Node.
/** the set of builtin constructors that don't have side effects. */
private static final Set<String> CONSTRUCTORS_WITHOUT_SIDE_EFFECTS =
new HashSet<String>(Arrays.asList(
"Array",
"Date",
"Error",
"Object",
"RegExp",
"XMLHttpRequest"));
public static final String CONSTANT_MARKER = "$$constant";
// Utility class; do not instantiate.
private NodeUtil() {}
/**
* Gets the boolean value of a node that represents a literal
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>. This method
* effectively emulates the <code>Boolean()</code> JavaScript cast function.
*
* @throws IllegalArgumentException If {@code n} is not a literal value
*/
static boolean getBooleanValue(Node n) {
switch (n.getType()) {
case Token.STRING:
return n.getString().length() > 0;
case Token.NUMBER:
return n.getDouble() != 0;
case Token.NULL:
case Token.FALSE:
case Token.VOID:
return false;
case Token.NAME:
String name = n.getString();
if ("undefined".equals(name)
|| "NaN".equals(name)) {
// We assume here that programs don't change the value of the keyword
// undefined to something other than the value undefined.
return false;
} else if ("Infinity".equals(name)) {
return true;
}
break;
case Token.TRUE:
case Token.ARRAYLIT:
case Token.OBJECTLIT:
case Token.REGEXP:
return true;
}
throw new IllegalArgumentException("Non-literal value: " + n);
}
/**
* Gets the value of a node as a String, or null if it cannot be converted.
* When it returns a non-null String, this method effectively emulates the
* <code>String()</code> JavaScript cast function.
*/
static String getStringValue(Node n) {
// TODO(user): Convert constant array, object, and regex literals as well.
switch (n.getType()) {
case Token.NAME:
case Token.STRING:
return n.getString();
case Token.NUMBER:
double value = n.getDouble();
long longValue = (long) value;
// Return "1" instead of "1.0"
if (longValue == value) {
return Long.toString(longValue);
} else {
return Double.toString(n.getDouble());
}
case Token.FALSE:
case Token.TRUE:
case Token.NULL:
return Node.tokenToName(n.getType());
case Token.VOID:
return "undefined";
}
return null;
}
/**
* Gets the function's name. This method recognizes five forms:
* <ul>
* <li>{@code function name() ...}</li>
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS> * <li>{@code var name = function() ...}</li>
* <li>{@code qualified.name = function() ...}</li>
* <li>{@code var name2 = function name1() ...}</li>
* <li>{@code qualified.name2 = function name1() ...}</li>
* </ul>
* In two last cases with named anonymous functions, the second name is
* returned (the variable of qualified name).
*
* @param n a node whose type is {@link Token#FUNCTION}
* @param parent {@code n}'s parent (never {@code null})
* @return the function's name, or {@code null} if it has no name
*/
static String getFunctionName(Node n, Node parent) {
String name = n.getFirstChild().getString();
switch (parent.getType()) {
case Token.NAME:
// var name = function() ...
// var name2 = function name1() ...
return parent.getString();
case Token.ASSIGN:
// qualified.name = function() ...
// qualified.name2 = function name1() ...
return parent.getFirstChild().getQualifiedName();
default:
// function name() ...
return name != null && name.length() != 0 ? name : null;
}
}
/**
* Returns true if this is an immutable value.
*/
static boolean isImmutableValue(Node n) {
switch (n.getType()) {
case Token.STRING:
case Token.NUMBER:
case Token.NULL:
case Token.TRUE:
case Token.FALSE:
case Token.VOID:
return true;
case Token.NEG:
return isImmutableValue(n.getFirstChild());
case Token.NAME:
String name = n.getString();
// We assume here that programs don't change the value of the keyword
// undefined to something other than the value undefined.
return "undefined".equals(name)
|| "Infinity".equals(name)
|| "NaN".equals(name);
}
return false;
}
/**
* Returns true if this is a literal value. We define a literal value
* as any node that evaluates to the same thing regardless of when or
* where it is evaluated. So /xyz/ and [3, 5] are literals, but
* function()
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS> { return a; } is not.
*/
static boolean isLiteralValue(Node n) {
// TODO(nicksantos): Refine this function to catch more literals.
switch (n.getType()) {
case Token.ARRAYLIT:
case Token.OBJECTLIT:
case Token.REGEXP:
// Return true only if all children are const.
for (Node child = n.getFirstChild(); child != null;
child = child.getNext()) {
if (!isLiteralValue(child)) {
return false;
}
}
return true;
default:
return isImmutableValue(n);
}
}
/**
* Determines whether the given value may be assigned to a define.
*
* @param val The value being assigned.
* @param defines The list of names of existing defines.
*/
static boolean isValidDefineValue(Node val, Set<String> defines) {
switch (val.getType()) {
case Token.STRING:
case Token.NUMBER:
case Token.TRUE:
case Token.FALSE:
return true;
// Single operators are valid if the child is valid.
case Token.BITAND:
case Token.BITNOT:
case Token.BITOR:
case Token.BITXOR:
case Token.NOT:
case Token.NEG:
return isValidDefineValue(val.getFirstChild(), defines);
// Names are valid if and only if they are defines themselves.
case Token.NAME:
case Token.GETPROP:
if (val.isQualifiedName()) {
return defines.contains(val.getQualifiedName());
}
}
return false;
}
/**
* Returns whether this a BLOCK node with no children.
*
* @param block The node.
*/
static boolean isEmptyBlock(Node block) {
if (block.getType() != Token.BLOCK) {
return false;
}
for (Node n = block.getFirstChild(); n != null; n = n.getNext()) {
if (n.getType() != Token.EMPTY) {
return false;
}
}
return true;
}
/**
* A "simple" operator is one whose children are expressions,
* has no direct side-effects (unlike '+='), and has no
* conditional aspects (unlike '||').
*/
static boolean is
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS> know to be safe
switch (n.getType()) {
// other side-effect free statements and expressions
case Token.AND:
case Token.BLOCK:
case Token.EXPR_RESULT:
case Token.HOOK:
case Token.IF:
case Token.IN:
case Token.LP:
case Token.NUMBER:
case Token.OR:
case Token.THIS:
case Token.TRUE:
case Token.FALSE:
case Token.NULL:
case Token.STRING:
case Token.SWITCH:
case Token.TRY:
case Token.EMPTY:
break;
// Throws are by definition side effects
case Token.THROW:
return true;
case Token.OBJECTLIT:
case Token.ARRAYLIT:
case Token.REGEXP:
if (checkForNewObjects) {
return true;
}
break;
case Token.VAR: // empty var statement (no declaration)
case Token.NAME: // variable by itself
if (n.getFirstChild() != null)
return true;
break;
case Token.FUNCTION:
// Anonymous functions don't have side-effects, but named ones
// change the namespace. Therefore, we check if the function has
// a name. Either way, we don't need to check the children, since
// they aren't executed at declaration time.
//
return !isFunctionAnonymous(n);
case Token.NEW:
{
if (checkForNewObjects) {
return true;
}
// calls to constructors that have no side effects have the
// no side effect property set.
if (n.isNoSideEffectsCall()) {
break;
}
// certain constructors are certified side effect free
Node constructor = n.getFirstChild();
if (Token.NAME == constructor.getType()) {
String className = constructor.getString();
if (CONSTRUCTORS_WITHOUT_SIDE_EFFECTS.contains(className)) {
// loop below will see if the constructor parameters have
// side-effects
break;
}
} else {
// the constructor could also be an expression like
// new (useArray ? Object : Array)();
}
}
return true;
case Token.CALL:
// calls to functions that have no side effects have the no
// side effect property set.
if (n.isNoSide
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>EffectsCall()) {
// loop below will see if the function parameters have
// side-effects
break;
}
return true;
default:
if (isSimpleOperatorType(n.getType()))
break;
if (isAssignmentOp(n)) {
// Assignments will have side effects if
// a) The RHS has side effects, or
// b) The LHS has side effects, or
// c) A name on the LHS will exist beyond the life of this statement.
if (checkForStateChangeHelper(
n.getFirstChild(), checkForNewObjects) ||
checkForStateChangeHelper(
n.getLastChild(), checkForNewObjects)) {
return true;
}
Node current = n.getFirstChild();
for (;
current.getType() == Token.GETPROP ||
current.getType() == Token.GETELEM;
current = current.getFirstChild()) { }
return !(isLiteralValue(current) ||
current.getType() == Token.FUNCTION);
}
return true;
}
for (Node c = n.getFirstChild(); c != null; c = c.getNext()) {
if (checkForStateChangeHelper(c, checkForNewObjects)) {
return true;
}
}
return false;
}
/**
* Do calls to this constructor have side effects?
*
* @param callNode - construtor call node
*/
static boolean constructorCallHasSideEffects(Node callNode) {
Preconditions.checkArgument(
callNode.getType() == Token.NEW,
"Expected NEW node, got " + Token.name(callNode.getType()));
if (callNode.isNoSideEffectsCall()) {
return false;
}
Node nameNode = callNode.getFirstChild();
if (nameNode.getType() == Token.NAME &&
CONSTRUCTORS_WITHOUT_SIDE_EFFECTS.contains(nameNode.getString())) {
return false;
}
return true;
}
/**
* Returns true if calls to this function have side effects.
*
* @param callNode - function call node
*/
static boolean functionCallHasSideEffects(Node callNode) {
Preconditions.checkArgument(
callNode.getType() == Token.CALL,
"Expected CALL node, got " + Token.name(callNode.getType()));
if (
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>callNode.isNoSideEffectsCall()) {
return false;
}
Node nameNode = callNode.getFirstChild();
// Built-in functions with no side effects.
if (nameNode.getType() == Token.NAME) {
String name = nameNode.getString();
if (name.equals("String")) {
return false;
}
}
// Functions in the "Math" namespace have no side effects.
if (nameNode.getType() == Token.GETPROP &&
nameNode.getFirstChild().getType() == Token.NAME) {
String namespaceName = nameNode.getFirstChild().getString();
if (namespaceName.equals("Math")) {
return false;
}
}
return true;
}
/**
* Returns true if the current node's type implies side effects.
*
* This is a non-recursive version of the may have side effects
* check; used to check wherever the current node's type is one of
* the reason's why a subtree has side effects.
*/
static boolean nodeTypeMayHaveSideEffects(Node n) {
if (NodeUtil.isAssignmentOp(n)) {
return true;
}
switch(n.getType()) {
case Token.CALL:
case Token.DELPROP:
case Token.NEW:
case Token.DEC:
case Token.INC:
case Token.THROW:
return true;
case Token.NAME:
// A variable definition.
return n.hasChildren();
default:
return false;
}
}
/**
* @return Whether the tree can be affected by side-effects or
* has side-effects.
*/
static boolean canBeSideEffected(Node n) {
Set<String> emptySet = Collections.emptySet();
return canBeSideEffected(n, emptySet);
}
/**
* @param knownConstants A set of names known to be constant value at
* node 'n' (such as locals that are last written before n can execute).
* @return Whether the tree can be affected by side-effects or
* has side-effects.
*/
static boolean canBeSideEffected(Node n, Set<String> knownConstants) {
switch (n.getType()) {
case Token.CALL:
case Token.NEW:
// Function calls or
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS> constructor can reference changed values.
// TODO(johnlenz): Add some mechanism for determining that functions
// are unaffected by side effects.
return true;
case Token.NAME:
// Non-constant names values may have been changed.
return !NodeUtil.isConstantName(n)
&& !knownConstants.contains(n.getString());
// Properties on constant NAMEs can still be side-effected.
case Token.GETPROP:
case Token.GETELEM:
return true;
}
for (Node c = n.getFirstChild(); c != null; c = c.getNext()) {
if (canBeSideEffected(c, knownConstants)) {
return true;
}
}
return false;
}
/*
* 0 comma ,
* 1 assignment = += -= *= /= %= <<= >>= >>>= &= ^= |=
* 2 conditional ?:
* 3 logical-or ||
* 4 logical-and &&
* 5 bitwise-or |
* 6 bitwise-xor ^
* 7 bitwise-and &
* 8 equality == !=
* 9 relational < <= > >=
* 10 bitwise shift << >> >>>
* 11 addition/subtraction + -
* 12 multiply/divide * / %
* 13 negation/increment ! ~ - ++ --
* 14 call, member () [] .
*/
static int precedence(int type) {
switch (type) {
case Token.COMMA: return 0;
case Token.ASSIGN_BITOR:
case Token.ASSIGN_BITXOR:
case Token.ASSIGN_BITAND:
case Token.ASSIGN_LSH:
case Token.ASSIGN_RSH:
case Token.ASSIGN_URSH:
case Token.ASSIGN_ADD:
case Token.ASSIGN_SUB:
case Token.ASSIGN_MUL:
case Token.ASSIGN_DIV:
case Token.ASSIGN_MOD:
case Token.ASSIGN: return 1;
case Token.HOOK: return 2; // ?: operator
case Token.OR: return 3;
case Token.AND: return 4;
case Token.BITOR: return 5;
case Token.BITXOR: return 6;
case Token.
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS> /**
* Is this a GETPROP node?
*/
static boolean isGetProp(Node n) {
return n.getType() == Token.GETPROP;
}
/**
* Is this a NAME node?
*/
static boolean isName(Node n) {
return n.getType() == Token.NAME;
}
/**
* Is this a NEW node?
*/
static boolean isNew(Node n) {
return n.getType() == Token.NEW;
}
/**
* Is this a VAR node?
*/
static boolean isVar(Node n) {
return n.getType() == Token.VAR;
}
/**
* Is this node the name of a variable being declared?
*
* @param n The node
* @return True if {@code n} is NAME and {@code parent} is VAR
*/
static boolean isVarDeclaration(Node n) {
// There is no need to verify that parent != null because a NAME node
// always has a parent in a valid parse tree.
return n.getType() == Token.NAME && n.getParent().getType() == Token.VAR;
}
/**
* For an assignment or variable declaration get the assigned value.
* @return The value node representing the new value.
*/
static Node getAssignedValue(Node n) {
Preconditions.checkState(isName(n));
Node parent = n.getParent();
if (isVar(parent)) {
return n.getFirstChild();
} else if (isAssign(parent) && parent.getFirstChild() == n) {
return n.getNext();
} else {
return null;
}
}
/**
* Is this a STRING node?
*/
static boolean isString(Node n) {
return n.getType() == Token.STRING;
}
/**
* Is this node an assignment expression statement?
*
* @param n The node
* @return True if {@code n} is EXPR_RESULT and {@code n}'s
* first child is ASSIGN
*/
static boolean isExprAssign(Node n) {
return n.getType() == Token.EXPR_RESULT
&& n.getFirstChild().getType() == Token.ASSIGN;
}
/**
* Is this an ASSIGN node?
*/
static boolean isAssign(Node
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>);
Node parent = block.getParent();
// Try to remove the block if its parent is a block/script or if its
// parent is label and it has exactly one child.
if (NodeUtil.isStatementBlock(parent)) {
Node previous = block;
while (block.hasChildren()) {
Node child = block.removeFirstChild();
parent.addChildAfter(child, previous);
previous = child;
}
parent.removeChild(block);
return true;
} else if (parent.getType() == Token.LABEL && block.hasOneChild()) {
parent.replaceChild(block, block.removeFirstChild());
return true;
} else {
return false;
}
}
/**
* Is this a CALL node?
*/
static boolean isCall(Node n) {
return n.getType() == Token.CALL;
}
/**
* Is this a FUNCTION node?
*/
static boolean isFunction(Node n) {
return n.getType() == Token.FUNCTION;
}
/**
* Return a BLOCK node for the given FUNCTION node.
*/
static Node getFunctionBody(Node fn) {
Preconditions.checkArgument(isFunction(fn));
return fn.getLastChild();
}
/**
* Is this a THIS node?
*/
static boolean isThis(Node node) {
return node.getType() == Token.THIS;
}
/**
* Is this node or any of its children a CALL?
*/
static boolean containsCall(Node n) {
return containsType(n, Token.CALL);
}
/**
* Is this node a function declaration? A function declaration is a function
* that has a name that is added to the current scope (i.e. a function that
* is not anonymous; see {@link #isFunctionAnonymous}).
*/
static boolean isFunctionDeclaration(Node n) {
return n.getType() == Token.FUNCTION && !isFunctionAnonymous(n);
}
/**
* Is this node a hoisted function declaration? A function declaration in the
* scope root is hoisted to the top of the scope.
* See {@link #isFunctionDeclaration}).
*/
static boolean isHoistedFunctionDeclaration(Node n) {
return NodeUtil.isFunctionDeclaration(n)
&& (n.getParent().getType() == Token.SCRIPT
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS> || n.getParent().getParent().getType() == Token.FUNCTION);
}
/**
* Is this node an anonymous function? An anonymous function is one that has
* either no name or a name that is not added to the current scope (see
* {@link #isFunctionAnonymous}).
*/
static boolean isAnonymousFunction(Node n) {
return n.getType() == Token.FUNCTION && isFunctionAnonymous(n);
}
/**
* Is a FUNCTION node an anonymous function? An anonymous function is one that
* has either no name or a name that is not added to the current scope.
*
* <p>Some examples of anonymous functions:
* <pre>
* function () {}
* (function f() {})()
* [ function f() {} ]
* var f = function f() {};
* for (function f() {};;) {}
* </pre>
*
* <p>Some examples of functions that are <em>not</em> anonymous:
* <pre>
* function f() {}
* if (x); else function f() {}
* for (;;) { function f() {} }
* </pre>
*
* @param n A FUNCTION node
* @return Whether n is an anonymous function
*/
static boolean isFunctionAnonymous(Node n) {
return !isStatement(n);
}
/**
* Determines if a function takes a variable number of arguments by
* looking for references to the "arguments" var_args object.
*/
static boolean isVarArgsFunction(Node function) {
Preconditions.checkArgument(isFunction(function));
return NodeUtil.isNameReferenced(
function.getLastChild(),
"arguments",
Predicates.<Node>not(new NodeUtil.MatchNodeType(Token.FUNCTION)));
}
/**
* @return Whether node is a call to methodName.
* a.f(...)
* a['f'](...)
*/
static boolean isObjectCallMethod(Node callNode, String methodName) {
if (callNode.getType() == Token.CALL) {
Node functionIndentifyingExpression = callNode.getFirstChild();
if (NodeUtil.isGet(functionIndentifyingExpression)) {
Node last = functionIndentifyingExpression.getLastChild();
if (last != null && last.getType() == Token.STRING) {
String propName
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS> = last.getString();
return (propName.equals(methodName));
}
}
}
return false;
}
/**
* @return Whether the callNode represents an expression in the form of:
* x.call(...)
* x['call'](...)
*/
static boolean isFunctionObjectCall(Node callNode) {
return isObjectCallMethod(callNode, "call");
}
/**
* @return Whether the callNode represents an expression in the form of:
* x.apply(...)
* x['apply'](...)
*/
static boolean isFunctionObjectApply(Node callNode) {
return isObjectCallMethod(callNode, "apply");
}
/**
* @return Whether the callNode represents an expression in the form of:
* x.call(...)
* x['call'](...)
* where x is a NAME node.
*/
static boolean isSimpleFunctionObjectCall(Node callNode) {
if (isFunctionObjectCall(callNode)) {
if (callNode.getFirstChild().getFirstChild().getType() == Token.NAME) {
return true;
}
}
return false;
}
/**
* Determines whether this node is strictly on the left hand side of an assign
* or var initialization. Notably, this does not include all L-values, only
* statements where the node is used only as an L-value.
*
* @param n The node
* @param parent Parent of the node
* @return True if n is the left hand of an assign
*/
static boolean isLhs(Node n, Node parent) {
return (parent.getType() == Token.ASSIGN && parent.getFirstChild() == n) ||
parent.getType() == Token.VAR;
}
/**
* Determines whether a node represents an object literal key
* (e.g. key1 in {key1: value1, key2: value2}).
*
* @param node A node
* @param parent The node's parent
*/
static boolean isObjectLitKey(Node node, Node parent) {
if (node.getType() == Token.STRING && parent.getType() == Token.OBJECTLIT) {
int index = 0;
for (Node current = parent.getFirstChild();
current != null;
current =
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS> current.getNext()) {
if (current == node) {
return index % 2 == 0;
}
index++;
}
}
return false;
}
/**
* Converts an operator's token value (see {@link Token}) to a string
* representation.
*
* @param operator the operator's token value to convert
* @return the string representation or {@code null} if the token value is
* not an operator
*/
static String opToStr(int operator) {
switch (operator) {
case Token.BITOR: return "|";
case Token.OR: return "||";
case Token.BITXOR: return "^";
case Token.AND: return "&&";
case Token.BITAND: return "&";
case Token.SHEQ: return "===";
case Token.EQ: return "==";
case Token.NOT: return "!";
case Token.NE: return "!=";
case Token.SHNE: return "!==";
case Token.LSH: return "<<";
case Token.IN: return "in";
case Token.LE: return "<=";
case Token.LT: return "<";
case Token.URSH: return ">>>";
case Token.RSH: return ">>";
case Token.GE: return ">=";
case Token.GT: return ">";
case Token.MUL: return "*";
case Token.DIV: return "/";
case Token.MOD: return "%";
case Token.BITNOT: return "~";
case Token.ADD: return "+";
case Token.SUB: return "-";
case Token.POS: return "+";
case Token.NEG: return "-";
case Token.ASSIGN: return "=";
case Token.ASSIGN_BITOR: return "|=";
case Token.ASSIGN_BITXOR: return "^=";
case Token.ASSIGN_BITAND: return "&=";
case Token.ASSIGN_LSH: return "<<=";
case Token.ASSIGN_RSH: return ">>=";
case Token.ASSIGN_URSH: return ">>>=";
case Token.ASSIGN_ADD: return "+=";
case Token.ASSIGN_SUB: return "-=";
case Token.ASSIGN_MUL: return "*=";
case Token.ASSIGN_DIV: return "/=";
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>
case Token.ASSIGN_MOD: return "%=";
case Token.VOID: return "void";
case Token.TYPEOF: return "typeof";
case Token.INSTANCEOF: return "instanceof";
default: return null;
}
}
/**
* Converts an operator's token value (see {@link Token}) to a string
* representation or fails.
*
* @param operator the operator's token value to convert
* @return the string representation
* @throws Error if the token value is not an operator
*/
static String opToStrNoFail(int operator) {
String res = opToStr(operator);
if (res == null) {
throw new Error("Unknown op " + operator + ": " +
Token.name(operator));
}
return res;
}
/**
* @return true if n or any of its children are of the specified type.
* Does not traverse into functions.
*/
static boolean containsTypeInOuterScope(Node node, int type) {
return containsType(node, type,
Predicates.<Node>not(new NodeUtil.MatchNodeType(Token.FUNCTION)));
}
/**
* @return true if n or any of its children are of the specified type
*/
static boolean containsType(Node node,
int type,
Predicate<Node> traverseChildrenPred) {
return has(node, new MatchNodeType(type), traverseChildrenPred);
}
/**
* @return true if n or any of its children are of the specified type
*/
static boolean containsType(Node node, int type) {
return containsType(node, type, Predicates.<Node>alwaysTrue());
}
/**
* Given a node tree, finds all the VAR declarations in that tree that are
* not in an inner scope. Then adds a new VAR node at the top of the current
* scope that redeclares them, if necessary.
*/
static void redeclareVarsInsideBranch(Node branch) {
Collection<Node> vars = getVarsDeclaredInBranch(branch);
if (vars.isEmpty()) {
return;
}
Node parent = getAddingRoot(branch);
for (Node nameNode : vars) {
Node var = new Node(
Token.VAR, Node.newString(Token.NAME, nameNode.getString()));
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS> copyNameAnnotations(nameNode, var.getFirstChild());
parent.addChildToFront(var);
}
}
/**
* Copy any annotations that follow a named value.
* @param source
* @param destination
*/
static void copyNameAnnotations(Node source, Node destination) {
if (source.getBooleanProp(Node.IS_CONSTANT_NAME)) {
destination.putBooleanProp(Node.IS_CONSTANT_NAME, true);
}
}
/**
* Gets a Node at the top of the current scope where we can add new var
* declarations as children.
*/
private static Node getAddingRoot(Node n) {
Node addingRoot = null;
Node ancestor = n;
while (null != (ancestor = ancestor.getParent())) {
int type = ancestor.getType();
if (type == Token.SCRIPT) {
addingRoot = ancestor;
break;
} else if (type == Token.FUNCTION) {
addingRoot = ancestor.getLastChild();
break;
}
}
// make sure that the adding root looks ok
Preconditions.checkState(addingRoot.getType() == Token.BLOCK ||
addingRoot.getType() == Token.SCRIPT);
Preconditions.checkState(addingRoot.getFirstChild() == null ||
addingRoot.getFirstChild().getType() != Token.SCRIPT);
return addingRoot;
}
/** Creates function name(params_0, ..., params_n) { body }. */
public static FunctionNode newFunctionNode(String name, List<Node> params,
Node body, int lineno, int charno) {
Node parameterParen = new Node(Token.LP, lineno, charno);
for (Node param : params) {
parameterParen.addChildToBack(param);
}
FunctionNode function = new FunctionNode(name, lineno, charno);
function.addChildrenToBack(
Node.newString(Token.NAME, name, lineno, charno));
function.addChildToBack(parameterParen);
function.addChildToBack(body);
return function;
}
/**
* Creates a node representing a qualified name.
*
* @param name A qualified name (e.g. "foo" or "foo.bar.baz")
* @param lineno The source line offset.
* @param charno The source character offset from start
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS> c = s.charAt(index);
if (c > LARGEST_BASIC_LATIN) {
return false;
}
}
return true;
}
/**
* Determines whether the given name can appear on the right side of
* the dot operator. Many properties (like reserved words) cannot.
*/
static boolean isValidPropertyName(String name) {
return TokenStream.isJSIdentifier(name) &&
!TokenStream.isKeyword(name) &&
// no Unicode escaped characters - some browsers are less tolerant
// of Unicode characters that might be valid according to the
// language spec.
// Note that by this point, unicode escapes have been converted
// to UTF-16 characters, so we're only searching for character
// values, not escapes.
NodeUtil.isLatin(name);
}
private static class VarCollector implements Visitor {
final Map<String, Node> vars = Maps.newLinkedHashMap();
public void visit(Node n) {
if (n.getType() == Token.NAME) {
Node parent = n.getParent();
if (parent != null && parent.getType() == Token.VAR) {
String name = n.getString();
if (!vars.containsKey(name)) {
vars.put(name, n);
}
}
}
}
}
/**
* Retrieves vars declared in the current node tree, excluding descent scopes.
*/
public static Collection<Node> getVarsDeclaredInBranch(Node root) {
VarCollector collector = new VarCollector();
visitPreOrder(
root,
collector,
Predicates.<Node>not(new NodeUtil.MatchNodeType(Token.FUNCTION)));
return collector.vars.values();
}
/**
* @return {@code true} if the node an assignment to a prototype property of
* some constructor.
*/
static boolean isPrototypePropertyDeclaration(Node n) {
if (!NodeUtil.isExprAssign(n)) {
return false;
}
return isPrototypeProperty(n.getFirstChild().getFirstChild());
}
static boolean isPrototypeProperty(Node n) {
String lhsString = n.getQualifiedName();
if (lhsString == null) {
return false;
}
int prototypeIdx = lhsString.indexOf(".prototype.");
return prototypeIdx != -1;
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>
}
/**
* @return The class name part of a qualified prototype name.
*/
static Node getPrototypeClassName(Node qName) {
Node cur = qName;
while (isGetProp(cur)) {
if (cur.getLastChild().getString().equals("prototype")) {
return cur.getFirstChild();
} else {
cur = cur.getFirstChild();
}
}
return null;
}
/**
* @return The string property name part of a qualified prototype name.
*/
static String getPrototypePropertyName(Node qName) {
String qNameStr = qName.getQualifiedName();
int prototypeIdx = qNameStr.lastIndexOf(".prototype.");
int memberIndex = prototypeIdx + ".prototype".length() + 1;
return qNameStr.substring(memberIndex);
}
/**
* Create a node for an empty result expression:
* "void 0"
*/
static Node newUndefinedNode() {
// TODO(johnlenz): Why this instead of the more common "undefined"?
return new Node(Token.VOID, Node.newNumber(0));
}
/**
* Create a VAR node containing the given name and initial value expression.
*/
static Node newVarNode(String name, Node value) {
Node nodeName = Node.newString(Token.NAME, name);
if (value != null) {
nodeName.addChildrenToBack(value);
}
Node var = new Node(Token.VAR, nodeName);
return var;
}
/**
* A predicate for matching name nodes with the specified node.
*/
private static class MatchNameNode implements Predicate<Node>{
final String name;
MatchNameNode(String name){
this.name = name;
}
public boolean apply(Node n) {
return n.getType() == Token.NAME
&& n.getString().equals(name);
}
}
/**
* A predicate for matching nodes with the specified type.
*/
static class MatchNodeType implements Predicate<Node>{
final int type;
MatchNodeType(int type){
this.type = type;
}
public boolean apply(Node n) {
return n.getType() == type;
}
}
/**
* Whether a Node type is within the node tree.
*/
static boolean isNodeTypeReferenced(
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS> X="continue";id=Id_continue; break L;
case 'd': X="debugger";id=Id_debugger; break L;
case 'f': X="function";id=Id_function; break L;
case 'v': X="volatile";id=Id_volatile; break L;
} break L;
case 9: c=s.charAt(0);
if (c=='i') { X="interface";id=Id_interface; }
else if (c=='p') { X="protected";id=Id_protected; }
else if (c=='t') { X="transient";id=Id_transient; }
break L;
case 10: c=s.charAt(1);
if (c=='m') { X="implements";id=Id_implements; }
else if (c=='n') { X="instanceof";id=Id_instanceof; }
break L;
case 12: X="synchronized";id=Id_synchronized; break L;
}
if (X!=null && X!=s && !X.equals(s)) id = 0;
}
// #/generated#
// #/string_id_map#
if (id == 0) { return Token.EOF; }
return id & 0xff;
}
public static boolean isJSIdentifier(String s) {
int length = s.length();
if (length == 0 || !Character.isJavaIdentifierStart(s.charAt(0)))
return false;
for (int i=1; i<length; i++) {
char c = s.charAt(i);
if (!Character.isJavaIdentifierPart(c)) {
if (c == '\\') {
if (! ((i + 5) < length)
&& (s.charAt(i + 1) == 'u')
&& 0 <= Kit.xDigitToInt(s.charAt(i + 2), 0)
&& 0 <= Kit.xDigitToInt(s.charAt(i + 3), 0)
&& 0 <= Kit.xDigitToInt(s.charAt(i + 4), 0)
&& 0 <= Kit.xDigitToInt(s.charAt(i + 5), 0
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS> path to the Jar.
private String originalPath = null;
// Remember the offset for the previous line query. If the next line
// is after this point, we can start scanning at the previous offset rather
// than starting at the beginning of the file.
private int lastOffset;
private int lastLine;
private String code = null;
/**
* Construct a new abstract source file.
*
* @param fileName The file name of the source file. It does not necessarily
* need to correspond to a real path. But it should be unique. Will
* appear in warning messages emitted by the compiler.
*/
SourceFile(String fileName) {
this.fileName = fileName;
// Starting point: offset 0 is at line 1.
this.lastOffset = 0;
this.lastLine = 1;
}
//////////////////////////////////////////////////////////////////////////////
// Implementation
/**
* Gets all the code in this source file.
* @throws IOException
*/
public String getCode() throws IOException {
return code;
}
@VisibleForTesting
String getCodeNoCache() {
return code;
}
private void setCode(String sourceCode) {
code = sourceCode;
}
public String getOriginalPath() {
return originalPath != null ? originalPath : fileName;
}
public void setOriginalPath(String originalPath) {
this.originalPath = originalPath;
}
// For SourceFile types which cache source code that can be regenerated
// easily, flush the cache. We maintain the cache mostly to speed up
// generating source when displaying error messages, so dumping the file
// contents after the compile is a fine thing to do.
public void clearCachedSource() {
// By default, do nothing. Not all kinds of SourceFiles can regenerate
// code.
}
/** Returns a unique name for the source file. */
public String getName() {
return fileName;
}
/**
* Gets the source line for the indicated line number.
*
* @param lineNumber the line number, 1 being the first line of the file.
* @return The line indicated. Does not include the newline at the end
* of the file. Returns {@code null} if it does not exist,
* or if there was an IO exception.
*/
public String get
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>(String sourceName) {
this.sourceName = sourceName;
}
public final int getEncodedSourceStart() { return encodedSourceStart; }
public final int getEncodedSourceEnd() { return encodedSourceEnd; }
public final void setEncodedSourceBounds(int start, int end) {
this.encodedSourceStart = start;
this.encodedSourceEnd = end;
}
public final int getBaseLineno() { return baseLineno; }
public final void setBaseLineno(int lineno) {
// One time action
if (lineno < 0 || baseLineno >= 0) Kit.codeBug();
baseLineno = lineno;
}
public final int getEndLineno() { return endLineno; }
public final void setEndLineno(int lineno) {
// One time action
if (lineno < 0 || endLineno >= 0) Kit.codeBug();
endLineno = lineno;
}
public final int getFunctionCount() {
if (functions == null) { return 0; }
return functions.size();
}
public final FunctionNode getFunctionNode(int i) {
return (FunctionNode)functions.get(i);
}
public final int addFunction(FunctionNode fnNode) {
if (fnNode == null) Kit.codeBug();
if (functions == null) { functions = new ObjArray(); }
functions.add(fnNode);
return functions.size() - 1;
}
public final int getRegexpCount() {
if (regexps == null) { return 0; }
return regexps.size() / 2;
}
public final String getRegexpString(int index) {
return (String)regexps.get(index * 2);
}
public final String getRegexpFlags(int index) {
return (String)regexps.get(index * 2 + 1);
}
public final int addRegexp(String string, String flags) {
if (string == null) Kit.codeBug();
if (regexps == null) { regexps = new ObjArray(); }
regexps.add(string);
regexps.add(flags);
return regexps.size() / 2 - 1;
}
public final boolean hasParamOrVar
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>(String name) {
return itsVariableNames.has(name);
}
public final int getParamOrVarIndex(String name) {
return itsVariableNames.get(name, -1);
}
public final String getParamOrVarName(int index) {
return (String)itsVariables.get(index);
}
public final int getParamCount() {
return varStart;
}
public final int getParamAndVarCount() {
return itsVariables.size();
}
public final String[] getParamAndVarNames() {
int N = itsVariables.size();
if (N == 0) {
return ScriptRuntime.emptyStrings;
}
String[] array = new String[N];
itsVariables.toArray(array);
return array;
}
public final boolean[] getParamAndVarConst() {
int N = itsVariables.size();
boolean[] array = new boolean[N];
for (int i = 0; i < N; i++)
if (itsConst.get(i) != null)
array[i] = true;
return array;
}
public final void addParam(String name) {
// Check addparam is not called after addLocal
if (varStart != itsVariables.size()) Kit.codeBug();
// Allow non-unique parameter names: use the last occurrence (parser
// will warn about dups)
int index = varStart++;
itsVariables.add(name);
itsConst.add(null);
itsVariableNames.put(name, index);
}
public static final int NO_DUPLICATE = 1;
public static final int DUPLICATE_VAR = 0;
public static final int DUPLICATE_PARAMETER = -1;
public static final int DUPLICATE_CONST = -2;
/**
* This function adds a variable to the set of var declarations for a
* function (or script). This returns an indicator of a duplicate that
* overrides a formal parameter (false if this dups a parameter).
* @param name variable name
* @return 1 if the name is not any form of duplicate, 0 if it duplicates a
* non-parameter, -1 if it duplicates a parameter and -2 if it duplicates a
* const.
*/
public final int
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS> addVar(String name) {
int vIndex = itsVariableNames.get(name, -1);
if (vIndex != -1) {
// There's already a variable or parameter with this name.
if (vIndex >= varStart) {
Object v = itsConst.get(vIndex);
if (v != null)
return DUPLICATE_CONST;
else
return DUPLICATE_VAR;
} else
return DUPLICATE_PARAMETER;
}
int index = itsVariables.size();
itsVariables.add(name);
itsConst.add(null);
itsVariableNames.put(name, index);
return NO_DUPLICATE;
}
public final boolean addConst(String name) {
int vIndex = itsVariableNames.get(name, -1);
if (vIndex != -1) {
// There's already a variable or parameter with this name.
return false;
}
int index = itsVariables.size();
itsVariables.add(name);
itsConst.add(name);
itsVariableNames.put(name, index);
return true;
}
public final void removeParamOrVar(String name) {
int i = itsVariableNames.get(name, -1);
if (i != -1) {
itsVariables.remove(i);
itsVariableNames.remove(name);
ObjToIntMap.Iterator iter = itsVariableNames.newIterator();
for (iter.start(); !iter.done(); iter.next()) {
int v = iter.getValue();
if (v > i) {
iter.setValue(v - 1);
}
}
}
}
public final Object getCompilerData()
{
return compilerData;
}
public final void setCompilerData(Object data)
{
if (data == null) throw new IllegalArgumentException();
// Can only call once
if (compilerData != null) throw new IllegalStateException();
compilerData = data;
}
private int encodedSourceStart;
private int encodedSourceEnd;
private String sourceName;
private int baseLineno = -1;
private int endLineno = -1;
private ObjArray functions;
private ObjArray regexps;
// a list of the formal parameters and local variables
private ObjArray itsVariables
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>/*
* Copyright 2004 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.javascript.rhino.Node;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
import java.util.Stack;
/**
* CodePrinter prints out js code in either pretty format or compact format.
*
* @see CodeGenerator
*
*
*/
class CodePrinter {
// The number of characters after which we insert a line break in the code
static final int DEFAULT_LINE_LENGTH_THRESHOLD = 500;
// There are two separate CodeConsumers, one for pretty-printing and
// another for compact printing. Both implement the interface
// HasGetCode as CodeConsumer does not have a method for getting the
// formatted string.
// There are two implementations because the CompactCodePrinter
// potentially has a very different implementation to the pretty
// version.
private interface HasGetCode {
String getCode();
}
private abstract static class MappedCodePrinter extends CodeConsumer {
final private Stack<Mapping> mappings;
final private List<Mapping> allMappings;
final private boolean createSrcMap;
MappedCodePrinter(boolean createSrcMap) {
this.createSrcMap = createSrcMap;
this.mappings = createSrcMap ? new Stack<Mapping>() : null;
this.allMappings = createSrcMap ? new ArrayList<Mapping>() : null;
}
/**
* Maintains a mapping from a given node to the position
* in the source code at which its generated form was
* placed. This position
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS> is relative only to the current
* run of the CodeConsumer and will be normalized
* later on by the SourceMap.
*
* @see SourceMap
*/
private static class Mapping {
Node node;
Position start;
Position end;
}
/**
* Starts the source mapping for the given
* node at the current position.
*/
@Override
void startSourceMapping(Node node) {
if (createSrcMap
&& node.getProp(Node.SOURCEFILE_PROP) != null
&& node.getLineno() > 0) {
int line = getCurrentLineIndex();
int index = getCurrentCharIndex();
// If the index is -1, we are not performing any mapping.
if (index >= 0) {
Mapping mapping = new Mapping();
mapping.node = node;
mapping.start = new Position(line, index);
mappings.push(mapping);
allMappings.add(mapping);
}
}
}
/**
* Finishes the source mapping for the given
* node at the current position.
*/
@Override
void endSourceMapping(Node node) {
if (createSrcMap
&& node.getProp(Node.SOURCEFILE_PROP) != null
&& node.getLineno() > 0) {
int line = getCurrentLineIndex();
int index = getCurrentCharIndex();
// If the index is -1, we are not performing any mapping.
if (index >= 0) {
Preconditions.checkState(
!mappings.empty(), "Mismatch in start and end of mapping");
Mapping mapping = mappings.pop();
mapping.end = new Position(line, index);
}
}
}
/**
* Generates the source map from the given code consumer,
* appending the information it saved to the SourceMap
* object given.
*/
@Override
void generateSourceMap(SourceMap map){
if (createSrcMap) {
for (Mapping mapping : allMappings) {
map.addMapping(mapping.node, mapping.start, mapping.end);
}
}
}
/**
* Reports to the code consumer that the given line has been cut at the
* given position (i.e. a \n has been inserted there). All mappings in
* the source maps after that position will be renormalized
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>Threshold;
}
public String getCode() {
return code.toString();
}
@Override
char getLastChar() {
return (code.length() > 0) ? code.charAt(code.length() - 1) : '\0';
}
@Override
int getCurrentBufferLength() {
return code.length();
}
@Override
int getCurrentCharIndex() {
return lineLength;
}
@Override
int getCurrentLineIndex() {
return lineIndex;
}
/**
* Appends a string to the code, keeping track of the current line length.
*/
@Override
void append(String str) {
// For pretty printing: indent at the beginning of the line
if (lineLength == 0) {
for (int i = 0; i < indent; i++) {
code.append(INDENT);
lineLength += INDENT.length();
}
}
code.append(str);
lineLength += str.length();
}
/**
* Adds a newline to the code, resetting the line length and handling
* indenting for pretty printing.
*/
@Override
void startNewLine() {
if (lineLength > 0) {
code.append('\n');
lineIndex++;
lineLength = 0;
}
}
@Override
void maybeLineBreak() {
maybeCutLine();
}
/**
* This may start a new line if the current line is longer than the line
* length threshold.
*/
@Override
void maybeCutLine() {
if (lineLength > lineLengthThreshold) {
startNewLine();
}
}
@Override
void endLine() {
startNewLine();
}
@Override
void appendBlockStart() {
append(" {");
indent++;
}
@Override
void appendBlockEnd() {
endLine();
indent--;
append("}");
}
@Override
void listSeparator() {
add(", ");
maybeLineBreak();
}
@Override
void endFunction(boolean statementContext) {
super.endFunction(statementContext);
if (statementContext) {
startNewLine();
}
}
@Override
void beginCaseBody() {
super.beginCaseBody();
indent++;
endLine();
}
@Override
void endCase
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>
this.outputCharset = outCharset;
return this;
}
/**
* Whether the input AST guaranteed to be properly formed, fail if it isn't.
*/
Builder setValidation(boolean validation) {
this.validation = validation;
return this;
}
/**
* Generates the source code and returns it.
*/
String build() {
if (root == null) {
throw new IllegalStateException(
"Cannot build without root node being specified");
}
Format outputFormat = outputTypes
? Format.TYPED
: prettyPrint
? Format.PRETTY
: Format.COMPACT;
return toSource(root, outputFormat, lineBreak, lineLengthThreshold,
sourceMap, outputCharset, validation);
}
}
enum Format {
COMPACT,
PRETTY,
TYPED
}
/**
* Converts a tree to js code
*/
private static String toSource(Node root, Format outputFormat,
boolean lineBreak, int lineLengthThreshold,
SourceMap sourceMap,
Charset outputCharset,
boolean validation) {
boolean createSourceMap = (sourceMap != null);
CodeConsumer cp =
outputFormat == Format.COMPACT
? new CompactCodePrinter(
lineBreak, lineLengthThreshold, createSourceMap)
: new PrettyCodePrinter(lineLengthThreshold, createSourceMap);
CodeGenerator cg =
outputFormat == Format.TYPED
? new TypedCodeGenerator(cp, outputCharset)
: new CodeGenerator(cp, outputCharset, validation);
cg.add(root);
String code = ((HasGetCode) cp).getCode();
if (createSourceMap) {
cp.generateSourceMap(sourceMap);
}
return code;
}
}
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>
right, blindScope, condition);
}
// right type
JSType rightType = getTypeIfRefinable(right, blindScope);
boolean rightIsRefineable;
if (rightType != null) {
rightIsRefineable = true;
} else {
rightIsRefineable = false;
rightType = right.getJSType();
blindScope = firstPreciserScopeKnowingConditionOutcome(
right, blindScope, condition);
}
if (condition) {
rightType = (rightType == null) ? null :
rightType.getRestrictedTypeGivenToBooleanOutcome(condition);
// creating new scope
if ((leftType != null && leftIsRefineable) ||
(rightType != null && rightIsRefineable)) {
FlowScope informed = blindScope.createChildFlowScope();
if (leftIsRefineable && leftType != null) {
declareNameInScope(informed, left, leftType);
}
if (rightIsRefineable && rightType != null) {
declareNameInScope(informed, right, rightType);
}
return informed;
}
}
return blindScope;
}
private FlowScope caseAndOrMaybeShortCircuiting(Node left, Node right,
FlowScope blindScope, boolean condition) {
FlowScope leftScope = firstPreciserScopeKnowingConditionOutcome(
left, blindScope, !condition);
StaticSlot<JSType> leftVar = leftScope.findUniqueRefinedSlot(blindScope);
if (leftVar == null) {
return blindScope;
}
FlowScope rightScope = firstPreciserScopeKnowingConditionOutcome(
left, blindScope, condition);
rightScope = firstPreciserScopeKnowingConditionOutcome(
right, rightScope, !condition);
StaticSlot<JSType> rightVar = rightScope.findUniqueRefinedSlot(blindScope);
if (rightVar == null || !leftVar.getName().equals(rightVar.getName())) {
return blindScope;
}
JSType type = leftVar.getType().getLeastSupertype(rightVar.getType());
FlowScope informed = blindScope.createChildFlowScope();
informed.inferSlotType(leftVar.getName(), type);
return informed;
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS> }
private FlowScope caseNameOrGetProp(Node name, FlowScope blindScope,
boolean outcome) {
JSType type = getTypeIfRefinable(name, blindScope);
if (type != null) {
JSType restrictedType =
type.getRestrictedTypeGivenToBooleanOutcome(outcome);
FlowScope informed = blindScope.createChildFlowScope();
declareNameInScope(informed, name, restrictedType);
return informed;
}
return blindScope;
}
private FlowScope caseTypeOf(Node node, JSType type, String value,
boolean resultEqualsValue, FlowScope blindScope) {
JSType restrictedType =
getRestrictedByTypeOfResult(type, value, resultEqualsValue);
if (restrictedType == null) {
return blindScope;
}
FlowScope informed = blindScope.createChildFlowScope();
declareNameInScope(informed, node, restrictedType);
return informed;
}
private FlowScope caseInstanceOf(Node left, Node right, FlowScope blindScope,
boolean outcome) {
JSType leftType = getTypeIfRefinable(left, blindScope);
if (leftType == null) {
return blindScope;
}
JSType rightType = right.getJSType();
ObjectType targetType =
typeRegistry.getNativeObjectType(JSTypeNative.UNKNOWN_TYPE);
if (rightType instanceof FunctionType) {
targetType = (FunctionType) rightType;
}
Visitor<JSType> visitor;
if (outcome) {
visitor = new RestrictByTrueInstanceOfResultVisitor(targetType);
} else {
visitor = new RestrictByFalseInstanceOfResultVisitor(targetType);
}
JSType restrictedLeftType = leftType.visit(visitor);
if (restrictedLeftType != null && !restrictedLeftType.equals(leftType)) {
FlowScope informed = blindScope.createChildFlowScope();
declareNameInScope(informed, left, restrictedLeftType);
return informed;
}
return blindScope;
}
/**
* Given 'property in object', ensures that the object has the property in the
* informed scope by defining it as a qualified name if the object type lacks
* the property and it's not in the blind scope.
* @param object The node of the right-
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS> code, '$' is often a namespace delimiter. To allow inlining
// of namespaced constants, we strip off any namespaces here.
int pos = name.lastIndexOf('$');
if (pos >= 0) {
name = name.substring(pos + 1);
if (name.length() == 0) {
return false;
}
}
if (!Character.isUpperCase(name.charAt(0))) {
return false;
}
// hack way of checking that there aren't any lower-case letters
return name.toUpperCase().equals(name);
}
/**
* {@inheritDoc}
*
* <p>This enforces Google's convention about enum key names. They must match
* the regular expression {@code [A-Z0-9][A-Z0-9_]*}.
*
* <p>Examples:
* <ul>
* <li>A</li>
* <li>213</li>
* <li>FOO_BAR</li>
* </ul>
*/
@Override
public boolean isValidEnumKey(String key) {
return ENUM_KEY_PATTERN.matcher(key).matches();
}
/**
* {@inheritDoc}
*
* <p>In Google code, parameter names beginning with {@code opt_} are
* treated as optional arguments.
*/
@Override
public boolean isOptionalParameter(Node parameter) {
return parameter.getString().startsWith(OPTIONAL_ARG_PREFIX);
}
@Override
public boolean isVarArgsParameter(Node parameter) {
return VAR_ARGS_NAME.equals(parameter.getString());
}
/**
* {@inheritDoc}
*
* <p>In Google code, any global name starting with an underscore is
* considered exported.
*/
@Override
public boolean isExported(String name, boolean local) {
return !local && name.startsWith("_");
}
/**
* {@inheritDoc}
*
* <p>In Google code, private names end with an underscore, and exported
* names are never considered private (see {@link #isExported}).
*/
@Override
public boolean isPrivate(String name) {
return name.endsWith("_") && !isExported(name);
}
}
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>/*
* Copyright 2009 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp.parsing;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;
import com.google.javascript.jscomp.mozilla.rhino.CompilerEnvirons;
import com.google.javascript.jscomp.mozilla.rhino.Context;
import com.google.javascript.jscomp.mozilla.rhino.ErrorReporter;
import com.google.javascript.jscomp.mozilla.rhino.EvaluatorException;
import com.google.javascript.jscomp.mozilla.rhino.Parser;
import com.google.javascript.jscomp.mozilla.rhino.ast.AstRoot;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.jstype.JSTypeRegistry;
import java.io.IOException;
import java.util.ResourceBundle;
import java.util.Set;
import java.util.logging.Logger;
public class ParserRunner {
private static final String configResource =
"com.google.javascript.jscomp.parsing.ParserConfig";
private static Set<String> annotationNames = null;
// Should never need to instantiate class of static methods.
private ParserRunner() {}
public static Config createConfig(
JSTypeRegistry typeRegistry, boolean isIdeMode) {
return new Config(
typeRegistry, getAnnotationNames(), isIdeMode);
}
/**
* Gets a list of extra annotations that are OK, even if the parser
* doesn't have handlers for them built-in.
*/
static Set<String> getAnnotationNames() {
init
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>AnnotationNames();
return annotationNames;
}
private static synchronized void initAnnotationNames() {
if (annotationNames != null) {
return;
}
Set<String> trimmedNames = Sets.newHashSet();
ResourceBundle config = ResourceBundle.getBundle(configResource);
String[] names = config.getString("jsdoc.annotations").split(",");
for (String name : names) {
trimmedNames.add(name.trim());
}
annotationNames = ImmutableSet.copyOf(trimmedNames);
}
/**
* Parses the JavaScript text given by a reader.
*
* @param sourceName The filename.
* @param sourceString Source code from the file.
* @param errorReporter An error.
* @param logger A logger.
* @return The AST of the given text.
* @throws IOException
*/
public static Node parse(String sourceName,
String sourceString,
Config config,
ErrorReporter errorReporter,
Logger logger) throws IOException {
Context cx = Context.enter();
cx.setErrorReporter(errorReporter);
cx.setLanguageVersion(Context.VERSION_1_5);
CompilerEnvirons compilerEnv = new CompilerEnvirons();
compilerEnv.initFromContext(cx);
compilerEnv.setRecordingComments(true);
compilerEnv.setRecordingLocalJsDocComments(true);
compilerEnv.setWarnTrailingComma(true);
if (config.isIdeMode) {
compilerEnv.setReservedKeywordAsIdentifier(true);
compilerEnv.setAllowMemberExprAsFunctionName(true);
}
Parser p = new Parser(compilerEnv, errorReporter);
AstRoot astRoot = null;
try {
astRoot = p.parse(sourceString, sourceName, 1);
} catch (EvaluatorException e) {
logger.info("Error parsing " + sourceName + ": " + e.getMessage());
} finally {
Context.exit();
}
Node root = null;
if (astRoot != null) {
root = IRFactory.transformTree(
astRoot, sourceString, config, errorReporter);
root.setIsSyntheticBlock(true);
}
return root;
}
}
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS> * Covert EXPR_VOID to EXPR_RESULT to simplify the rest of the code.
*/
private void normalizeNodeTypes(Node n) {
if (n.getType() == Token.EXPR_VOID) {
n.setType(Token.EXPR_RESULT);
reportChange();
}
// Remove unused properties to minimize differences between ASTs
// produced by the two parsers.
if (n.getType() == Token.FUNCTION) {
Preconditions.checkState(n.getProp(Node.FUNCTION_PROP) == null);
}
normalizeBlocks(n);
for (Node child = n.getFirstChild();
child != null; child = child.getNext()) {
// This pass is run during the CompilerTestCase validation, so this
// parent pointer check serves as a more general check.
Preconditions.checkState(child.getParent() == n);
normalizeNodeTypes(child);
}
}
/**
* Add blocks to IF, WHILE, DO, etc.
*/
private void normalizeBlocks(Node n) {
if (NodeUtil.isControlStructure(n)
&& n.getType() != Token.LABEL
&& n.getType() != Token.SWITCH) {
for (Node c = n.getFirstChild(); c != null; c = c.getNext()) {
if (NodeUtil.isControlStructureCodeBlock(n,c) &&
c.getType() != Token.BLOCK) {
Node newBlock = new Node(Token.BLOCK);
n.replaceChild(c, newBlock);
if (c.getType() != Token.EMPTY) {
newBlock.addChildrenToFront(c);
} else {
newBlock.setWasEmptyNode(true);
}
c = newBlock;
reportChange();
}
}
}
}
/**
* Normalize where annotations appear on the AST. Copies
* around existing JSDoc annotations as well as internal annotations.
*/
static class PrepareAnnotations
extends NodeTraversal.AbstractPostOrderCallback {
private final AbstractCompiler compiler;
private final CodingConvention convention;
PrepareAnnotations(AbstractCompiler compiler) {
this.compiler = compiler;
this.convention = compiler.getCodingConvention();
}
/**
*
* In the AST that Rhino gives us, it needs to make a distinction
* between jsdoc
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS> on the object literal node and jsdoc on the object literal
* value. For example,
* <pre>
* var x = {
* / JSDOC /
* a: 'b',
* c: / JSDOC / 'd'
* };
* </pre>
*
* But in few narrow cases (in particular, function literals), it's
* a lot easier for us if the doc is attached to the value.
*/
public void visit(NodeTraversal t, Node n, Node parent) {
int nType = n.getType();
switch (nType) {
case Token.NAME:
case Token.STRING:
String nString = n.getString();
if (nType == Token.NAME &&
n.getParent().getType() == Token.CALL &&
"eval".equals(nString)) {
n.putBooleanProp(Node.DIRECT_EVAL, true);
}
if (convention.isConstant(nString)) {
n.putBooleanProp(Node.IS_CONSTANT_NAME, true);
}
break;
case Token.FUNCTION:
JSDocInfo fnInfo = n.getJSDocInfo();
if (fnInfo == null) {
// Look for the info on other nodes.
if (parent.getType() == Token.ASSIGN) {
// on ASSIGNs
fnInfo = parent.getJSDocInfo();
} else if (parent.getType() == Token.NAME) {
// on var NAME = function() { ... };
fnInfo = parent.getParent().getJSDocInfo();
}
}
// Compute which function parameters are optional and
// which are var_args.
Node args = n.getFirstChild().getNext();
for (Node arg = args.getFirstChild();
arg != null;
arg = arg.getNext()) {
String argName = arg.getString();
JSTypeExpression typeExpr = fnInfo == null ?
null : fnInfo.getParameterType(argName);
if (convention.isOptionalParameter(arg) ||
typeExpr != null && typeExpr.isOptionalArg()) {
arg.putBooleanProp(Node.IS_OPTIONAL_PARAM, true);
}
if (convention.isVarArgsParameter(arg) ||
typeExpr != null && typeExpr.isVarArgs())
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>/*
* Copyright 2009 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.collect.Lists;
import com.google.javascript.jscomp.MakeDeclaredNamesUnique.InlineRenamer;
import com.google.javascript.rhino.Node;
/**
* @author johnlenz@google.com (John Lenz)
*/
public class MakeDeclaredNamesUniqueTest extends CompilerTestCase {
private boolean useDefaultRenamer = false;
private boolean invert = false;
private boolean removeConst = false;
private final String localNamePrefix = "unique_";
@Override
public CompilerPass getProcessor(final Compiler compiler) {
if (!invert) {
return new CompilerPass() {
@Override
public void process(Node externs, Node root) {
compiler.resetUniqueNameId();
MakeDeclaredNamesUnique renamer = null;
if (useDefaultRenamer) {
renamer = new MakeDeclaredNamesUnique();
} else {
renamer = new MakeDeclaredNamesUnique(
new InlineRenamer(
compiler.getUniqueNameIdSupplier(),
localNamePrefix,
removeConst));
}
NodeTraversal.traverseRoots(
compiler, Lists.newArrayList(externs, root), renamer);
}
};
} else {
return MakeDeclaredNamesUnique.getContextualRenameInverter(compiler);
}
}
@Override
protected int getNumRepetitions() {
// The normalize pass is only run once.
return 1;
}
@Override
public void setUp() {
removeConst = false;
invert = false;
useDefaultRenamer = false;
}
public void test
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>jstype.JSType;
import com.google.javascript.rhino.jstype.JSTypeNative;
import com.google.javascript.rhino.jstype.JSTypeRegistry;
import com.google.javascript.rhino.jstype.ObjectType;
import java.text.MessageFormat;
import java.util.Iterator;
import java.util.List;
/**
* A central reporter for all type violations: places where the programmer
* has annotated a variable (or property) with one type, but has assigned
* another type to it.
*
* Also doubles as a central repository for all type violations, so that
* type-based optimizations (like AmbiguateProperties) can be fault-tolerant.
*
* @author nicksantos@google.com (Nick Santos)
*/
class TypeValidator {
private final AbstractCompiler compiler;
private final JSTypeRegistry typeRegistry;
private final JSType allValueTypes;
// TODO(nicksantos): Provide accessors to better filter the list of type
// mismatches. For example, if we pass (Cake|null) where only Cake is
// allowed, that doesn't mean we should invalidate all Cakes.
private final List<TypeMismatch> mismatches = Lists.newArrayList();
// User warnings
private static final String FOUND_REQUIRED =
"{0}\n" +
"found : {1}\n" +
"required: {2}";
static final DiagnosticType INVALID_CAST =
DiagnosticType.warning("JSC_INVALID_CAST",
"invalid cast - must be a subtype or supertype\n" +
"from: {0}\n" +
"to : {1}");
static final DiagnosticType TYPE_MISMATCH_WARNING =
DiagnosticType.warning(
"JSC_TYPE_MISMATCH",
"{0}");
static final DiagnosticType MISSING_EXTENDS_TAG_WARNING =
DiagnosticType.warning(
"JSC_MISSING_EXTENDS_TAG",
"Missing @extends tag on type {0}");
static final DiagnosticType DUP_VAR_DECLARATION =
DiagnosticType.warning("JSC_DUP_VAR_DECLARATION",
"variable {0} redefined with type {1}, " +
"original definition at {2}:{3
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>
* @param t The node traversal.
* @param n The node to issue warnings on.
* @param overridingType The overriding type.
* @param hiddenType The type of the property being overridden.
* @param propertyName The name of the property, for use in the
* warning message.
* @param ownerType The type of the owner of the property, for use
* in the warning message.
*/
void expectCanOverride(NodeTraversal t, Node n, JSType overridingType,
JSType hiddenType, String propertyName, JSType ownerType) {
if (!overridingType.canAssignTo(hiddenType)) {
registerMismatch(overridingType, hiddenType);
compiler.report(
JSError.make(t, n, HIDDEN_PROPERTY_MISMATCH,
propertyName, ownerType.toString(),
hiddenType.toString(), overridingType.toString()));
}
}
/**
* Expect that the first type is the direct superclass of the second type.
*
* @param t The node traversal.
* @param n The node where warnings should point to.
* @param superObject The expected super instance type.
* @param subObject The sub instance type.
*/
void expectSuperType(NodeTraversal t, Node n, ObjectType superObject,
ObjectType subObject) {
FunctionType subCtor = subObject.getConstructor();
ObjectType declaredSuper =
subObject.getImplicitPrototype().getImplicitPrototype();
if (!declaredSuper.equals(superObject)) {
if (declaredSuper.equals(getNativeType(OBJECT_TYPE))) {
compiler.report(
JSError.make(t, n, MISSING_EXTENDS_TAG_WARNING,
subObject.toString()));
registerMismatch(superObject, declaredSuper);
} else {
mismatch(t.getSourceName(), n,
"mismatch in declaration of superclass type",
superObject, declaredSuper);
}
// Correct the super type.
if (!subCtor.hasCachedValues()) {
subCtor.setPrototypeBasedOn(superObject);
}
}
}
/**
* Expect that the first type can be cast to the second type. The first type
* should be either a subtype or supertype of the second.
*
* @param t The node traversal.
* @param n The node where
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS> warnings should point.
* @param type The type being cast from.
* @param castType The type being cast to.
*/
void expectCanCast(NodeTraversal t, Node n, JSType type, JSType castType) {
castType = castType.restrictByNotNullOrUndefined();
type = type.restrictByNotNullOrUndefined();
if (!type.canAssignTo(castType) && !castType.canAssignTo(type)) {
compiler.report(
JSError.make(t, n, INVALID_CAST,
castType.toString(), type.toString()));
registerMismatch(type, castType);
}
}
/**
* Expect that the given variable has not been declared with a type.
*
* @param sourceName The name of the source file we're in.
* @param n The node where warnings should point to.
* @param parent The parent of {@code n}.
* @param var The variable that we're checking.
* @param variableName The name of the variable.
* @param newType The type being applied to the variable. Mostly just here
* for the benefit of the warning.
*/
void expectUndeclaredVariable(String sourceName, Node n, Node parent, Var var,
String variableName, JSType newType) {
boolean allowDupe = false;
if (n.getType() == Token.GETPROP) {
JSDocInfo info = n.getJSDocInfo();
if (info == null) {
info = parent.getJSDocInfo();
}
allowDupe =
info != null && info.getSuppressions().contains("duplicate");
}
JSType varType = var.getType();
// Only report duplicate declarations that have types. Other duplicates
// will be reported by the syntactic scope creator later in the
// compilation process.
if (varType != null &&
varType != typeRegistry.getNativeType(UNKNOWN_TYPE) &&
newType != null &&
newType != typeRegistry.getNativeType(UNKNOWN_TYPE)) {
// If there are two typed declarations of the same variable, that
// is an error and the second declaration is ignored, except in the
// case of native types. A null input type means that the declaration
// was made in TypedScopeCreator#createInitial
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>Scope and is a
// native type.
if (var.input == null) {
n.setJSType(varType);
if (parent.getType() == Token.VAR) {
if (n.getFirstChild() != null) {
n.getFirstChild().setJSType(varType);
}
} else {
Preconditions.checkState(parent.getType() == Token.FUNCTION);
parent.setJSType(varType);
}
} else {
// Always warn about duplicates if the overridden type does not
// match the original type.
//
// If the types match, suppress the warning iff there was a @suppress
// tag, or if the original declaration was a stub.
if (!(allowDupe ||
var.getParentNode().getType() == Token.EXPR_RESULT) ||
!newType.equals(varType)) {
compiler.report(
JSError.make(sourceName, n, DUP_VAR_DECLARATION,
variableName, newType.toString(), var.getInputName(),
String.valueOf(var.nameNode.getLineno()),
varType.toString()));
}
}
}
}
/**
* Expect that all properties on interfaces that this type implements are
* implemented.
*/
void expectAllInterfacePropertiesImplemented(FunctionType type) {
ObjectType instance = type.getInstanceType();
for (ObjectType implemented : type.getAllImplementedInterfaces()) {
if (implemented.getImplicitPrototype() != null) {
for (String prop :
implemented.getImplicitPrototype().getOwnPropertyNames()) {
if (!instance.hasProperty(prop)) {
Node source = type.getSource();
Preconditions.checkNotNull(source);
String sourceName = (String) source.getProp(Node.SOURCENAME_PROP);
sourceName = sourceName == null ? "" : sourceName;
compiler.report(JSError.make(sourceName, source,
INTERFACE_METHOD_NOT_IMPLEMENTED,
prop, implemented.toString(), instance.toString()));
registerMismatch(instance, implemented);
}
}
}
}
}
/**
* Report a type mismatch
*/
private void mismatch(NodeTraversal t, Node n,
String msg, JSType found, JSType required) {
mismatch(t.getSourceName(), n, msg, found, required);
}
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>
private void mismatch(NodeTraversal t, Node n,
String msg, JSType found, JSTypeNative required) {
mismatch(t, n, msg, found, getNativeType(required));
}
private void mismatch(String sourceName, Node n,
String msg, JSType found, JSType required) {
registerMismatch(found, required);
compiler.report(
JSError.make(sourceName, n, TYPE_MISMATCH_WARNING,
formatFoundRequired(msg, found, required)));
}
private void registerMismatch(JSType found, JSType required) {
// Don't register a mismatch for differences in null or undefined or if the
// code didn't downcast.
found = found.restrictByNotNullOrUndefined();
required = required.restrictByNotNullOrUndefined();
if (found.canAssignTo(required) || required.canAssignTo(found)) {
return;
}
mismatches.add(new TypeMismatch(found, required));
if (found instanceof FunctionType &&
required instanceof FunctionType) {
FunctionType fnTypeA = ((FunctionType) found);
FunctionType fnTypeB = ((FunctionType) required);
Iterator<Node> paramItA = fnTypeA.getParameters().iterator();
Iterator<Node> paramItB = fnTypeB.getParameters().iterator();
while (paramItA.hasNext() && paramItB.hasNext()) {
registerIfMismatch(paramItA.next().getJSType(),
paramItB.next().getJSType());
}
registerIfMismatch(fnTypeA.getReturnType(), fnTypeB.getReturnType());
}
}
private void registerIfMismatch(JSType found, JSType required) {
if (found != null && required != null &&
!found.canAssignTo(required)) {
registerMismatch(found, required);
}
}
/**
* Formats a found/required error message.
*/
private String formatFoundRequired(String description, JSType found,
JSType required) {
return MessageFormat.format(FOUND_REQUIRED, description, found, required);
}
/**
* Given a node, get a human-readable name for the type of that node so
* that will be easy for the programmer to find the original declaration.
*
* For example, if SubFoo's property "
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS> should log this and analyze to track
// down why it happens. This is not critical and will be resolved over
// time as the type checker is extended.
return getNativeType(UNKNOWN_TYPE);
} else {
return jsType;
}
}
private JSType getNativeType(JSTypeNative typeId) {
return typeRegistry.getNativeType(typeId);
}
/**
* Signals that the first type and the second type have been
* used interchangeably.
*
* Type-based optimizations should take this into account
* so that they don't wreck code with type warnings.
*/
static class TypeMismatch {
final JSType typeA;
final JSType typeB;
/**
* It's the responsibility of the class that creates the
* {@code TypeMismatch} to ensure that {@code a} and {@code b} are
* non-matching types.
*/
TypeMismatch(JSType a, JSType b) {
this.typeA = a;
this.typeB = b;
}
@Override public boolean equals(Object object) {
if (object instanceof TypeMismatch) {
TypeMismatch that = (TypeMismatch) object;
return (that.typeA.equals(this.typeA) && that.typeB.equals(this.typeB))
|| (that.typeB.equals(this.typeA) && that.typeA.equals(this.typeB));
}
return false;
}
@Override public int hashCode() {
return Objects.hashCode(typeA, typeB);
}
@Override public String toString() {
return "(" + typeA + ", " + typeB + ")";
}
}
}
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>/*
* Copyright 2009 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp.parsing;
import com.google.common.collect.ImmutableMap;
import com.google.javascript.rhino.jstype.JSTypeRegistry;
import java.util.Map;
import java.util.Set;
/**
* Configuration for the AST factory. Should be shared across AST creation
* for all files of a compilation process.
*
* @author nicksantos@google.com (Nick Santos)
*/
public class Config {
/**
* Central registry for type info.
*/
final JSTypeRegistry registry;
/**
* Whether to parse the descriptions of jsdoc comments.
*/
final boolean parseJsDocDocumentation;
/**
* Whether we're in ide mode.
*/
final boolean isIdeMode;
/**
* Recognized JSDoc annotations, mapped from their name to their internal
* representation.
*/
final Map<String, Annotation> annotationNames;
/**
* Annotation names.
*/
Config(JSTypeRegistry registry, Set<String> annotationWhitelist,
boolean isIdeMode) {
this.registry = registry;
this.annotationNames = buildAnnotationNames(annotationWhitelist);
this.parseJsDocDocumentation = isIdeMode;
this.isIdeMode = isIdeMode;
}
/**
* Create the annotation names from the user-specified
* annotation whitelist.
*/
private static Map<String, Annotation> buildAnnotationNames(
Set<String> annotationWhitelist) {
ImmutableMap.Builder<String, Annotation> annotationBuilder =
ImmutableMap.builder();
annotationBuilder.putAll(Annotation.recognizedAnnotations);
for (String unrecognized
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>JSC_BAD_JSDOC_ANNOTATION", "Parse error. {0}");
// A map of Rhino messages to their DiagnosticType.
private final Map<String, DiagnosticType> typeMap;
private final AbstractCompiler compiler;
/**
* For each message such as "Not a good use of {0}", replace the place
* holder {0} with a wild card that matches all possible strings.
* Also put the any non-place-holder in quotes for regex matching later.
*/
private String replacePlaceHolders(String s) {
s = Pattern.quote(s);
return s.replaceAll("\\{\\d+\\}", "\\\\E.*\\\\Q");
}
private RhinoErrorReporter(AbstractCompiler compiler) {
this.compiler = compiler;
typeMap = ImmutableMap.of(
// Extra @fileoverview
replacePlaceHolders(
ScriptRuntime.getMessage0("msg.jsdoc.fileoverview.extra")),
EXTRA_FILEOVERVIEW,
// Trailing comma
replacePlaceHolders(
com.google.javascript.jscomp.mozilla.rhino.ScriptRuntime
.getMessage0("msg.extra.trailing.comma")),
TRAILING_COMMA,
// Duplicate parameter
replacePlaceHolders(
com.google.javascript.jscomp.mozilla.rhino.ScriptRuntime
.getMessage0("msg.dup.parms")),
DUPLICATE_PARAM,
// Unknown @annotations.
replacePlaceHolders(ScriptRuntime.getMessage0("msg.bad.jsdoc.tag")),
BAD_JSDOC_ANNOTATION);
}
public static com.google.javascript.jscomp.mozilla.rhino.ErrorReporter
forNewRhino(AbstractCompiler compiler) {
return new NewRhinoErrorReporter(compiler);
}
public static ErrorReporter forOldRhino(AbstractCompiler compiler) {
return new OldRhinoErrorReporter(compiler);
}
public void warning(String message, String sourceName, int line,
String lineSource, int lineOffset) {
compiler.report(
makeError(message, sourceName, line, lineOffset, CheckLevel.WARNING));
}
public void error(String message, String sourceName, int line,
String lineSource, int lineOffset) {
compiler.report(
makeError(message, source
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>Override
public boolean isNullable() {
return false;
}
@Override
public TernaryValue testForEquality(JSType that) {
if (UNKNOWN.equals(super.testForEquality(that))) {
return UNKNOWN;
}
if (that.isUnknownType() || that.isSubtype(
getNativeType(JSTypeNative.NUMBER_STRING_BOOLEAN)) ||
that.isObject()) {
return UNKNOWN;
}
return FALSE;
}
@Override
public boolean isBooleanValueType() {
return true;
}
@Override
public boolean matchesNumberContext() {
return true;
}
@Override
public boolean matchesStringContext() {
return true;
}
@Override
public boolean matchesObjectContext() {
// TODO(user): Revisit this for ES4, which is stricter.
return true;
}
@Override
public JSType autoboxesTo() {
return getNativeType(JSTypeNative.BOOLEAN_OBJECT_TYPE);
}
@Override
public String toString() {
return "boolean";
}
@Override
public BooleanLiteralSet getPossibleToBooleanOutcomes() {
return BooleanLiteralSet.BOTH;
}
@Override
public <T> T visit(Visitor<T> visitor) {
return visitor.caseBooleanType();
}
}
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>/*
* Copyright 2007 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.google.javascript.jscomp.GlobalNamespace.Name;
import com.google.javascript.jscomp.GlobalNamespace.Ref;
import com.google.javascript.jscomp.NodeTraversal.Callback;
import com.google.javascript.rhino.JSDocInfo;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import java.text.MessageFormat;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Process variables annotated as {@code @define}. A define is
* a special constant that may be overridden by later files and
* manipulated by the compiler, much like C preprocessor {@code #define}s.
*
* @author nicksantos@google.com (Nick Santos)
*/
class ProcessDefines implements CompilerPass {
/**
* Defines in this set will not be flagged with "unknown define" warnings.
* There are legacy flags that always set these defines, even when they
* might not be in the binary.
*/
private static final Set<String> KNOWN_DEFINES =
Sets.newHashSet("COMPILED");
private final AbstractCompiler compiler;
private final Map<String, Node> dominant
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS> = def.getValue();
Node inputValue = dominantReplacements.get(defineName);
Node finalValue = inputValue != null ?
inputValue : info.getLastValue();
if (finalValue != info.initialValue) {
info.initialValueParent.replaceChild(
info.initialValue, finalValue.cloneTree());
compiler.addToDebugLog("Overriding @define variable " + defineName);
changed = changed ||
finalValue.getType() != info.initialValue.getType() ||
!finalValue.isEquivalentTo(info.initialValue);
}
}
if (changed) {
compiler.reportCodeChange();
}
Set<String> unusedReplacements = dominantReplacements.keySet();
unusedReplacements.removeAll(allDefines.keySet());
unusedReplacements.removeAll(KNOWN_DEFINES);
for (String unknownDefine : unusedReplacements) {
compiler.report(JSError.make(UNKNOWN_DEFINE_WARNING, unknownDefine));
}
}
private static String format(MessageFormat format, Object... params) {
return format.format(params);
}
/**
* Finds all defines, and creates a {@link DefineInfo} data structure for
* each one.
* @return A map of {@link DefineInfo} structures, keyed by name.
*/
private Map<String, DefineInfo> collectDefines(Node root,
GlobalNamespace namespace) {
// Find all the global names with a @define annotation
List<Name> allDefines = Lists.newArrayList();
for (Name name : namespace.getNameIndex().values()) {
if (name.docInfo != null && name.docInfo.isDefine()) {
allDefines.add(name);
} else if (name.refs != null) {
for (Ref ref : name.refs) {
Node n = ref.node;
Node parent = ref.node.getParent();
JSDocInfo info = n.getJSDocInfo();
if (info == null &&
parent.getType() == Token.VAR && parent.hasOneChild()) {
info = parent.getJSDocInfo();
}
if (info != null && info.isDefine()) {
allDefines.add(name);
break;
}
}
}
}
CollectDefines pass = new CollectDefines(compiler, all
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>Defines);
NodeTraversal.traverse(compiler, root, pass);
return pass.getAllDefines();
}
/**
* Finds all assignments to @defines, and figures out the last value of
* the @define.
*/
private static final class CollectDefines implements Callback {
private final AbstractCompiler compiler;
private final Map<String, DefineInfo> assignableDefines;
private final Map<String, DefineInfo> allDefines;
private final Map<Node, RefInfo> allRefInfo;
// A hack that allows us to remove ASSIGN/VAR statements when
// we're currently visiting one of the children of the assign.
private Node lvalueToRemoveLater = null;
// A stack tied to the node traversal, to keep track of whether
// we're in a conditional block. If 1 is at the top, assignment to
// a define is allowed. Otherwise, it's not allowed.
private final Deque<Integer> assignAllowed;
CollectDefines(AbstractCompiler compiler, List<Name> listOfDefines) {
this.compiler = compiler;
this.allDefines = Maps.newHashMap();
assignableDefines = Maps.newHashMap();
assignAllowed = new ArrayDeque<Integer>();
assignAllowed.push(1);
// Create a map of references to defines keyed by node for easy lookup
allRefInfo = Maps.newHashMap();
for (Name name : listOfDefines) {
if (name.declaration != null) {
allRefInfo.put(name.declaration.node,
new RefInfo(name.declaration, name));
}
if (name.refs != null) {
for (Ref ref : name.refs) {
// If there's a TWIN def, only put one of the twins in.
if (ref.getTwin() == null || !ref.getTwin().isSet()) {
allRefInfo.put(ref.node, new RefInfo(ref, name));
}
}
}
}
}
/**
* Get a map of {@link DefineInfo} structures, keyed by the name of
* the define.
*/
Map<String, DefineInfo> getAllDefines() {
return allDefines;
}
/**
* Keeps track of whether the traversal is in a conditional branch.
* We traverse all nodes of the parse tree.
*/
public boolean shouldTra
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>verse(NodeTraversal nodeTraversal, Node n,
Node parent) {
updateAssignAllowedStack(n, true);
return true;
}
public void visit(NodeTraversal t, Node n, Node parent) {
RefInfo refInfo = allRefInfo.get(n);
if (refInfo != null) {
Ref ref = refInfo.ref;
Name name = refInfo.name;
String fullName = name.fullName();
switch (ref.type) {
case SET_FROM_GLOBAL:
case SET_FROM_LOCAL:
Node valParent = getValueParent(ref);
Node val = valParent.getLastChild();
if (valParent.getType() == Token.ASSIGN && name.isSimpleName() &&
name.declaration == ref) {
// For defines, it's an error if a simple name is assigned
// before it's declared
compiler.report(
JSError.make(t, val, INVALID_DEFINE_INIT_ERROR, fullName));
} else if (processDefineAssignment(t, fullName, val, valParent)) {
// remove the assignment so that the variable is still declared,
// but no longer assigned to a value, e.g.,
// DEF_FOO = 5; // becomes "5;"
// We can't remove the ASSIGN/VAR when we're still visiting its
// children, so we'll have to come back later to remove it.
refInfo.name.removeRef(ref);
lvalueToRemoveLater = valParent;
}
break;
default:
if (t.inGlobalScope()) {
// Treat this as a reference to a define in the global scope.
// After this point, the define must not be reassigned,
// or it's an error.
DefineInfo info = assignableDefines.get(fullName);
if (info != null) {
setDefineInfoNotAssignable(info, t);
assignableDefines.remove(fullName);
}
}
break;
}
}
if (!t.inGlobalScope() &&
n.getJSDocInfo() != null && n.getJSDocInfo().isDefine()) {
// warn about @define annotations in local scopes
compiler.report(
JSError.make(t, n, NON_GLOBAL_DEFINE_INIT_ERROR, ""));
}
if
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS> (lvalueToRemoveLater == n) {
lvalueToRemoveLater = null;
if (n.getType() == Token.ASSIGN) {
Node last = n.getLastChild();
n.removeChild(last);
parent.replaceChild(n, last);
} else {
Preconditions.checkState(n.getType() == Token.NAME);
n.removeChild(n.getFirstChild());
}
compiler.reportCodeChange();
}
if (n.getType() == Token.CALL) {
if (t.inGlobalScope()) {
// If there's a function call in the global scope,
// we just say it's unsafe and freeze all the defines.
//
// NOTE(nicksantos): We could be a lot smarter here. For example,
// ReplaceOverriddenVars keeps a call graph of all functions and
// which functions/variables that they reference, and tries
// to statically determine which functions are "safe" and which
// are not. But this would be overkill, expecially because
// the intended use of defines is with config_files, where
// all the defines are at the top of the bundle.
for (DefineInfo info : assignableDefines.values()) {
setDefineInfoNotAssignable(info, t);
}
assignableDefines.clear();
}
}
updateAssignAllowedStack(n, false);
}
/**
* Determines whether assignment to a define should be allowed
* in the subtree of the given node, and if not, records that fact.
*
* @param n The node whose subtree we're about to enter or exit.
* @param entering True if we're entering the subtree, false otherwise.
*/
private void updateAssignAllowedStack(Node n, boolean entering) {
switch (n.getType()) {
case Token.CASE:
case Token.FOR:
case Token.FUNCTION:
case Token.HOOK:
case Token.IF:
case Token.SWITCH:
case Token.WHILE:
if (entering) {
assignAllowed.push(0);
} else {
assignAllowed.remove();
}
break;
}
}
/**
* Determines whether assignment to a define should be allowed
* at the current point of the traversal.
*/
private boolean isAssignAllowed() {
return assignAllowed.element()
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS> == 1;
}
/**
* Tracks the given define.
*
* @param t The current traversal, for context.
* @param name The full name for this define.
* @param value The value assigned to the define.
* @param valueParent The parent node of value.
* @return Whether we should remove this assignment from the parse tree.
*/
private boolean processDefineAssignment(NodeTraversal t,
String name, Node value, Node valueParent) {
if (value == null || !NodeUtil.isValidDefineValue(value,
allDefines.keySet())) {
compiler.report(
JSError.make(t, value, INVALID_DEFINE_INIT_ERROR, name));
} else if (!isAssignAllowed()) {
compiler.report(
JSError.make(t, valueParent, NON_GLOBAL_DEFINE_INIT_ERROR, name));
} else {
DefineInfo info = allDefines.get(name);
if (info == null) {
// First declaration of this define.
info = new DefineInfo(value, valueParent);
allDefines.put(name, info);
assignableDefines.put(name, info);
} else if (info.recordAssignment(value)) {
// The define was already initialized, but this is a safe
// re-assignment.
return true;
} else {
// The define was already initialized, and this is an unsafe
// re-assignment.
compiler.report(
JSError.make(t, valueParent, DEFINE_NOT_ASSIGNABLE_ERROR,
name, info.getReasonWhyNotAssignable()));
}
}
return false;
}
/**
* Gets the parent node of the value for any assignment to a Name.
* For example, in the assignment
* {@code var x = 3;}
* the parent would be the NAME node.
*/
private static Node getValueParent(Ref ref) {
// there are two types of declarations: VARs and ASSIGNs
return ref.node.getParent() != null &&
ref.node.getParent().getType() == Token.VAR ?
ref.node : ref.node.getParent();
}
/**
* Records the fact that because of the current node in the node traversal,
* the define can't ever be assigned again.
*
* @param
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>} until requested by
* {@link #getControlFlowGraph()}. Note that {@link ArrayDeque} does not allow
* {@code null} elements, so {@link LinkedList} is used instead.
*/
Deque<ControlFlowGraph<Node>> cfgs = new LinkedList<ControlFlowGraph<Node>>();
/** The current source file name */
private String sourceName;
/** The scope creator */
private ScopeCreator scopeCreator;
/** Possible callback for scope entry and exist **/
private ScopedCallback scopeCallback;
/**
* Callback
*/
public interface Callback {
/**
* <p>Visits a node in pre order (before visiting its children) and decides
* whether this node's children should be traversed. If children are
* traversed, they will be visited by
* {@link #visit(NodeTraversal, Node, Node)} in post order.</p>
* <p>Implementations can have side effects (e.g. modifying the parse
* tree).</p>
* @return whether the children of this node should be visited
*/
boolean shouldTraverse(NodeTraversal nodeTraversal, Node n, Node parent);
/**
* <p>Visits a node in post order (after its children have been visited).
* A node is visited only if all its parents should be traversed
* ({@link #shouldTraverse(NodeTraversal, Node, Node)}).</p>
* <p>Implementations can have side effects (e.g. modifying the parse
* tree).</p>
*/
void visit(NodeTraversal t, Node n, Node parent);
}
/**
* Callback that also knows about scope changes
*/
public interface ScopedCallback extends Callback {
/**
* Called immediately after entering a new scope. The new scope can
* be accessed through t.getScope()
*/
void enterScope(NodeTraversal t);
/**
* Called immediately before exiting a scope. The ending scope can
* be accessed through t.getScope()
*/
void exitScope(NodeTraversal t);
}
/**
* Abstract callback to visit all nodes in post order.
*
*/
public abstract static class AbstractPostOrderCallback implements Callback {
public final boolean shouldTraverse(NodeTraversal nodeTraversal, Node n,
Node parent) {
return true;
}
}
/**
* Abstract callback to
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS> visit all nodes but not traverse into function
* bodies.
*/
public abstract static class AbstractShallowCallback implements Callback {
public final boolean shouldTraverse(NodeTraversal nodeTraversal, Node n,
Node parent) {
// We do want to traverse the name of a named function, but we don't
// want to traverse the arguments or body.
return parent == null || parent.getType() != Token.FUNCTION ||
n == parent.getFirstChild();
}
}
/**
* Abstract callback to visit all structure and statement nodes but doesn't
* traverse into functions or expressions.
*/
public abstract static class AbstractShallowStatementCallback
implements Callback {
public final boolean shouldTraverse(NodeTraversal nodeTraversal, Node n,
Node parent) {
return parent == null || NodeUtil.isControlStructure(parent)
|| NodeUtil.isStatementBlock(parent);
}
}
/**
* Abstract callback to visit a pruned set of nodes.
*
*/
public abstract static class AbstractNodeTypePruningCallback
implements Callback {
private final Set<Integer> nodeTypes;
private final boolean include;
/**
* Creates an abstract pruned callback.
* @param nodeTypes the nodes to include in the traversal
*/
public AbstractNodeTypePruningCallback(Set<Integer> nodeTypes) {
this(nodeTypes, true);
}
/**
* Creates an abstract pruned callback.
* @param nodeTypes the nodes to include/exclude in the traversal
* @param include whether to include or exclude the nodes in the traversal
*/
public AbstractNodeTypePruningCallback(Set<Integer> nodeTypes,
boolean include) {
this.nodeTypes = nodeTypes;
this.include = include;
}
public boolean shouldTraverse(NodeTraversal nodeTraversal, Node n,
Node parent) {
return include == nodeTypes.contains(n.getType());
}
}
/**
* Creates a node traversal using the specified callback interface.
*/
public NodeTraversal(AbstractCompiler compiler, Callback cb) {
this(compiler, cb, new SyntacticScopeCreator(compiler));
}
/**
* Creates a node traversal using the specified callback interface
* and the scope creator.
*/
public NodeTraversal(AbstractCompiler compiler, Callback cb,
ScopeCreator scopeCreator) {
this.callback = cb;
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>
if (cb instanceof ScopedCallback) {
this.scopeCallback = (ScopedCallback) cb;
}
this.compiler = compiler;
this.sourceName = "";
this.scopeCreator = scopeCreator;
}
private void throwUnexpectedException(Exception unexpectedException) {
// If there's an unexpected exception, try to get the
// line number of the code that caused it.
String message = unexpectedException.getMessage();
// TODO(user): It is possible to get more information if curNode or
// its parent is missing. We still have the scope stack in which it is still
// very useful to find out at least which function caused the exception.
if (!sourceName.isEmpty()) {
message =
unexpectedException.getMessage() + "\n" +
formatNodeContext("Node", curNode) +
(curNode == null ?
"" :
formatNodeContext("Parent", curNode.getParent()));
}
compiler.throwInternalError(message, unexpectedException);
}
private String formatNodeContext(String label, Node n) {
if (n == null) {
return " " + label + ": NULL";
}
return " " + label + "(" + n.toString(false, false, false) + "): "
+ formatNodePosition(n);
}
/**
* Traverses a parse tree recursively.
*/
public void traverse(Node root) {
try {
sourceName = "";
curNode = root;
pushScope(root);
traverseBranch(root, null);
popScope();
} catch (Exception unexpectedException) {
throwUnexpectedException(unexpectedException);
}
}
public void traverseRoots(Node ... roots) {
traverseRoots(Lists.newArrayList(roots));
}
public void traverseRoots(List<Node> roots) {
if (roots.isEmpty()) {
return;
}
try {
Node scopeRoot = roots.get(0).getParent();
Preconditions.checkState(scopeRoot != null);
sourceName = "";
curNode = scopeRoot;
pushScope(scopeRoot);
for (Node root : roots) {
Preconditions.checkState(root.getParent() == scopeRoot);
traverseBranch(root, scopeRoot);
}
popScope();
} catch (Exception unexpectedException) {
throwUnexpectedException(unexpectedException
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>code null}
*/
protected void traverseInnerNode(Node node, Node parent, Scope refinedScope) {
Preconditions.checkNotNull(parent);
if (refinedScope != null && getScope() != refinedScope) {
curNode = node;
pushScope(refinedScope);
traverseBranch(node, parent);
popScope();
} else {
traverseBranch(node, parent);
}
}
/**
* Gets the compiler.
*/
public Compiler getCompiler() {
// TODO(nicksantos): Remove this type cast. This is just temporary
// while refactoring.
return (Compiler) compiler;
}
/**
* Gets the current line number, or zero if it cannot be determined. The line
* number is retrieved lazily as a running time optimization.
*/
public int getLineNumber() {
Node cur = curNode;
while (cur != null) {
int line = cur.getLineno();
if (line >=0) {
return line;
}
cur = cur.getParent();
}
return 0;
}
/**
* Gets the current input source name.
*
* @return A string that may be empty, but not null
*/
public String getSourceName() {
return sourceName;
}
/**
* Gets the current input source.
*/
public CompilerInput getInput() {
return compiler.getInput(sourceName);
}
/**
* Gets the current input module.
*/
public JSModule getModule() {
CompilerInput input = getInput();
return input == null ? null : input.getModule();
}
/** Returns the node currently being traversed. */
public Node getCurrentNode() {
return curNode;
}
/**
* Traverses a node recursively.
*/
public static void traverse(
AbstractCompiler compiler, Node root, Callback cb) {
NodeTraversal t = new NodeTraversal(compiler, cb);
t.traverse(root);
}
/**
* Traverses a list of node trees.
*/
public static void traverseRoots(
AbstractCompiler compiler, List<Node> roots, Callback cb) {
NodeTraversal t = new NodeTraversal(compiler, cb);
t.traverseRoots(roots);
}
/**
* Traverses a branch.
*/
@SuppressWarnings("
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>fallthrough")
private void traverseBranch(Node n, Node parent) {
int type = n.getType();
if (type == Token.SCRIPT) {
sourceName = getSourceName(n);
}
curNode = n;
if (!callback.shouldTraverse(this, n, parent)) return;
switch (type) {
case Token.CATCH:
Preconditions.checkState(n.getChildCount() == 3);
Preconditions.checkState(n.getFirstChild().getType() == Token.NAME);
// the first child is the catch var and the third child
// is the code block
traverseBranch(n.getFirstChild(), n);
traverseBranch(n.getFirstChild().getNext().getNext(), n);
break;
case Token.FUNCTION:
traverseFunction(n, parent);
break;
default:
for (Node child = n.getFirstChild(); child != null; ) {
// child could be replaced, in which case our child node
// would no longer point to the true next
Node next = child.getNext();
traverseBranch(child, n);
child = next;
}
break;
}
curNode = n;
callback.visit(this, n, parent);
}
/**
* Traverses a function.
*/
private void traverseFunction(Node n, Node parent) {
Preconditions.checkState(n.getChildCount() == 3);
Preconditions.checkState(n.getType() == Token.FUNCTION);
final Node fnName = n.getFirstChild();
boolean anonymous = parent != null && NodeUtil.isFunctionAnonymous(n);
if (!anonymous) {
// Named functions are parent of the containing scope.
traverseBranch(fnName, n);
}
curNode = n;
pushScope(n);
if (anonymous) {
// Anonymous function names are parent of the contained scope.
traverseBranch(fnName, n);
}
final Node args = fnName.getNext();
final Node body = args.getNext();
// Args
traverseBranch(args, n);
// Body
Preconditions.checkState(body.getNext() == null &&
body.getType() == Token.BLOCK);
traverseBranch(body, n);
popScope();
}
/** Examines the functions stack for the last instance of a function node. */
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS> @SuppressWarnings("unchecked")
public Node getEnclosingFunction() {
if (scopes.size() + scopeRoots.size() < 2) {
return null;
} else {
if (scopeRoots.isEmpty()) {
return scopes.peek().getRootNode();
} else {
return scopeRoots.peek();
}
}
}
/** Creates a new scope (e.g. when entering a function). */
private void pushScope(Node node) {
Preconditions.checkState(curNode != null);
scopeRoots.push(node);
cfgs.push(null);
if (scopeCallback != null) {
scopeCallback.enterScope(this);
}
}
/** Creates a new scope (e.g. when entering a function). */
private void pushScope(Scope s) {
Preconditions.checkState(curNode != null);
scopes.push(s);
cfgs.push(null);
if (scopeCallback != null) {
scopeCallback.enterScope(this);
}
}
/** Pops back to the previous scope (e.g. when leaving a function). */
private void popScope() {
if (scopeCallback != null) {
scopeCallback.exitScope(this);
}
if (scopeRoots.isEmpty()) {
scopes.pop();
} else {
scopeRoots.pop();
}
cfgs.pop();
}
/** Gets the current scope. */
public Scope getScope() {
Scope scope = scopes.isEmpty() ? null : scopes.peek();
if (scopeRoots.isEmpty()) {
return scope;
}
Iterator<Node> it = scopeRoots.descendingIterator();
while (it.hasNext()) {
scope = scopeCreator.createScope(it.next(), scope);
scopes.push(scope);
}
scopeRoots.clear();
return scope;
}
/** Gets the control flow graph for the current JS scope. */
public ControlFlowGraph<Node> getControlFlowGraph() {
if (cfgs.peek() == null) {
ControlFlowAnalysis cfa = new ControlFlowAnalysis(compiler, false);
cfa.process(null, getScopeRoot());
cfgs.pop();
cfgs.push(cfa.getCfg());
}
return cfgs.peek();
}
/** Returns
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS> the current scope's root. */
public Node getScopeRoot() {
if (scopeRoots.isEmpty()) {
return scopes.peek().getRootNode();
} else {
return scopeRoots.peek();
}
}
/**
* Determines whether the traversal is currently in the global scope.
*/
boolean inGlobalScope() {
return getScopeDepth() <= 1;
}
int getScopeDepth() {
return scopes.size() + scopeRoots.size();
}
public boolean hasScope() {
return !(scopes.isEmpty() && scopeRoots.isEmpty());
}
/** Reports a diagnostic (error or warning) */
public void report(Node n, DiagnosticType diagnosticType,
String... arguments) {
JSError error = JSError.make(getSourceName(), n, diagnosticType, arguments);
compiler.report(error);
}
private static String getSourceName(Node n) {
String name = (String) n.getProp(Node.SOURCENAME_PROP);
return name == null ? "" : name;
}
}
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS> Remove this.
public boolean flowSensitiveInlineVariables;
/** Removes code associated with unused global names */
public boolean smartNameRemoval;
/** Removes code that will never execute */
public boolean removeDeadCode;
/** Checks for unreachable code */
public CheckLevel checkUnreachableCode;
/** Checks for missing return statements */
public CheckLevel checkMissingReturn;
/** Extracts common prototype member declarations */
public boolean extractPrototypeMemberDeclarations;
/** Removes functions that have no body */
public boolean removeEmptyFunctions;
/** Removes unused member prototypes */
public boolean removeUnusedPrototypeProperties;
/** Tells AnalyzePrototypeProperties it can remove externed props. */
public boolean removeUnusedPrototypePropertiesInExterns;
/** Removes unused variables */
public boolean removeUnusedVars;
/** Removes unused variables in global scope. */
public boolean removeUnusedVarsInGlobalScope;
/** Adds variable aliases for externals to reduce code size */
public boolean aliasExternals;
/**
* If set to a non-empty string, then during an alias externals pass only
* externals with these names will be considered for aliasing.
*/
public String aliasableGlobals;
/**
* Additional globals that can not be aliased since they may be undefined or
* can cause errors. Comma separated list of symbols. e.g. "foo,bar"
*/
public String unaliasableGlobals;
/** Collapses multiple variable declarations into one */
public boolean collapseVariableDeclarations;
/**
* Collapses anonymous function declarations into named function
* declarations
*/
public boolean collapseAnonymousFunctions;
/**
* If set to a non-empty set, those strings literals will be aliased to a
* single global instance per string, to avoid creating more objects than
* necessary.
*/
public Set<String> aliasableStrings;
/**
* A blacklist in the form of a regular expression to block strings that
* contains certain words from being aliased.
* If the value is the empty string, no words are blacklisted.
*/
public String aliasStringsBlacklist;
/**
* Aliases all string literals to global instances, to avoid creating more
* objects than necessary (if true, overrides any set of strings passed in
* to aliasableStrings)
*/
public boolean aliasAllStrings;
/** Print string usage as part of the compilation
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS> variable renaming map. */
public byte[] inputVariableMapSerialized;
/** Serialized input property renaming map. */
public byte[] inputPropertyMapSerialized;
/** Whether to export test functions. */
public boolean exportTestFunctions;
//--------------------------------
// Special-purpose alterations
//--------------------------------
/** Inserts runtime type assertions for debugging. */
boolean runtimeTypeCheck;
/**
* A JS function to be used for logging runtime type assertion
* failures. It will be passed the warning as a string and the
* faulty expression as arguments.
*/
String runtimeTypeCheckLogFunction;
/** A CodingConvention to use during the compile. */
private CodingConvention codingConvention;
/** Instrument code for the purpose of collecting coverage data. */
public boolean instrumentForCoverage;
/**
* Instrument code for the purpose of collecting coverage data - restrict to
* coverage pass only, and skip all other passes.
*/
public boolean instrumentForCoverageOnly;
/** Add code to skip properties that Caja adds to Object.prototype */
public boolean ignoreCajaProperties;
public String syntheticBlockStartMarker;
public String syntheticBlockEndMarker;
/** Compiling locale */
public String locale;
/** Sets the special "COMPILED" value to true */
public boolean markAsCompiled;
/** Removes try...catch...finally blocks for easier debugging */
public boolean removeTryCatchFinally;
/** Processes goog.provide() and goog.require() calls */
public boolean closurePass;
/** Rewrite new Date(goog.now()) to new Date(). */
boolean rewriteNewDateGoogNow;
/** Remove goog.abstractMethod assignments. */
boolean removeAbstractMethods;
/** Gather CSS names (requires closurePass) */
public boolean gatherCssNames;
/** Names of types to strip */
public Set<String> stripTypes;
/** Name suffixes that determine which variables and properties to strip */
public Set<String> stripNameSuffixes;
/** Name prefixes that determine which variables and properties to strip */
public Set<String> stripNamePrefixes;
/** Qualified type name prefixes that determine which types to strip */
public Set<String> stripTypePrefixes;
/** Custom passes */
public transient
Multimap<CustomPassExecutionTime, CompilerPass> customPasses;
/** Mark no side effect calls */
public boolean markNoSideEffectCalls;
/** Replacement
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>s for @defines. Will be Boolean, Numbers, or Strings */
private Map<String, Object> defineReplacements;
/** Move top level function declarations to the top */
public boolean moveFunctionDeclarations;
/** Instrumentation template to use */
public String instrumentationTemplate;
/**
* App identifier string for use by the instrumentation template's
* app_name_setter
*/
public String appNameStr;
/** Record function information */
public boolean recordFunctionInformation;
public boolean generateExports;
/** Map used in the renaming of CSS class names. */
public CssRenamingMap cssRenamingMap;
/** Process instances of goog.testing.ObjectPropertyString. */
boolean processObjectPropertyString;
/** Id generators to replace. */
Set<String> idGenerators;
//--------------------------------
// Output options
//--------------------------------
/** Output in pretty indented format */
public boolean prettyPrint;
/** Line break the output a bit more aggressively */
public boolean lineBreak;
/** Prints a separator comment before each js script */
public boolean printInputDelimiter;
/** The string to use as the separator for printInputDelimiter */
public String inputDelimiter = "// Input %num%";
/** Where to save a report of global name usage */
public String reportPath;
public TracerMode tracer;
private boolean colorizeErrorOutput;
public ErrorFormat errorFormat;
public String jsOutputFile;
private transient ComposeWarningsGuard warningsGuard;
//--------------------------------
// Special Output Options
//--------------------------------
/** The output path for the created externs file. */
String externExportsPath;
/** Where to save a cross-reference report from the name reference graph */
public String nameReferenceReportPath;
/** Where to save the name reference graph */
public String nameReferenceGraphPath;
//--------------------------------
// Debugging Options
//--------------------------------
/** The output path for the source map. */
public String sourceMapOutputPath;
/**
* Charset to use when generating code. If null, then output ASCII.
*/
public Charset outputCharset;
/**
* Initializes compiler options. All options are disabled by default.
*
* Command-line frontends to the compiler should set these properties
* like a builder.
*/
public CompilerOptions() {
// Checks
skipAllPasses = false;
nameAnonymousFunctionsOnly = false;
devMode = DevMode
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS> given type of warning to the given level.
*/
public void setWarningLevel(DiagnosticGroup type, CheckLevel level) {
addWarningsGuard(new DiagnosticGroupWarningsGuard(type, level));
}
WarningsGuard getWarningsGuard() {
return warningsGuard;
}
/**
* Add a guard to the set of warnings guards.
*/
public void addWarningsGuard(WarningsGuard guard) {
if (warningsGuard == null) {
warningsGuard = new ComposeWarningsGuard(guard);
} else {
warningsGuard.addGuard(guard);
}
}
/**
* Sets the variable and property renaming policies for the compiler,
* in a way that clears warnings about the renaming policy being
* uninitialized from flags.
*/
public void setRenamingPolicy(VariableRenamingPolicy newVariablePolicy,
PropertyRenamingPolicy newPropertyPolicy) {
this.variableRenaming = newVariablePolicy;
this.propertyRenaming = newPropertyPolicy;
}
/**
* If true, flattens multi-level property names on extern types
* (e.g. String$f = x). This should only be used with the typed version of
* the externs files.
*/
public void setCollapsePropertiesOnExternTypes(boolean collapse) {
collapsePropertiesOnExternTypes = collapse;
}
/**
* If true, process goog.testing.ObjectPropertyString instances.
*/
public void setProcessObjectPropertyString(boolean process) {
processObjectPropertyString = process;
}
/**
* Sets the id generators to replace.
*/
public void setIdGenerators(Set<String> idGenerators) {
this.idGenerators = Sets.newHashSet(idGenerators);
}
public void setRewriteNewDateGoogNow(boolean rewrite) {
this.rewriteNewDateGoogNow = rewrite;
}
public void setRemoveAbstractMethods(boolean remove) {
this.removeAbstractMethods = remove;
}
/**
* If true, name anonymous functions only. All other passes will be skipped.
*/
public void setNameAnonymousFunctionsOnly(boolean value) {
this.nameAnonymousFunctionsOnly = value;
}
public void setColorizeErrorOutput(boolean colorizeErrorOutput) {
this.colorizeErrorOutput = colorizeErrorOutput;
}
public boolean shouldColorizeErrorOutput()
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS> @Override
public TernaryValue testForEquality(JSType that) {
if (UNKNOWN.equals(super.testForEquality(that))) {
return UNKNOWN;
}
if (that.isUnknownType() || that.isSubtype(
getNativeType(JSTypeNative.OBJECT_NUMBER_STRING_BOOLEAN))) {
return UNKNOWN;
}
return FALSE;
}
@Override
public boolean isStringValueType() {
return true;
}
@Override
public boolean matchesNumberContext() {
return true;
}
@Override
public boolean matchesStringContext() {
return true;
}
@Override
public boolean matchesObjectContext() {
// TODO(user): Revisit this for ES4, which is stricter.
return true;
}
@Override
public String toString() {
return "string";
}
@Override
public JSType autoboxesTo() {
return getNativeType(JSTypeNative.STRING_OBJECT_TYPE);
}
@Override
public BooleanLiteralSet getPossibleToBooleanOutcomes() {
return BooleanLiteralSet.BOTH;
}
@Override
public <T> T visit(Visitor<T> visitor) {
return visitor.caseStringType();
}
}
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS> ObjToIntMap implements Serializable
{
static final long serialVersionUID = -1542220580748809402L;
// Map implementation via hashtable,
// follows "The Art of Computer Programming" by Donald E. Knuth
// ObjToIntMap is a copy cat of ObjToIntMap with API adjusted to object keys
public static class Iterator {
Iterator(ObjToIntMap master) {
this.master = master;
}
final void init(Object[] keys, int[] values, int keyCount) {
this.keys = keys;
this.values = values;
this.cursor = -1;
this.remaining = keyCount;
}
public void start() {
master.initIterator(this);
next();
}
public boolean done() {
return remaining < 0;
}
public void next() {
if (remaining == -1) Kit.codeBug();
if (remaining == 0) {
remaining = -1;
cursor = -1;
}else {
for (++cursor; ; ++cursor) {
Object key = keys[cursor];
if (key != null && key != DELETED) {
--remaining;
break;
}
}
}
}
public Object getKey() {
Object key = keys[cursor];
if (key == UniqueTag.NULL_VALUE) { key = null; }
return key;
}
public int getValue() {
return values[cursor];
}
public void setValue(int value) {
values[cursor] = value;
}
ObjToIntMap master;
private int cursor;
private int remaining;
private Object[] keys;
private int[] values;
}
public ObjToIntMap() {
this(4);
}
public ObjToIntMap(int keyCountHint) {
if (keyCountHint < 0) Kit.codeBug();
// Table grow when number of stored keys >= 3/4 of max capacity
int minimalCapacity = keyCountHint * 4 / 3;
int i;
for (i = 2; (1 << i) < minimalCapacity; ++i) { }
power = i;
if (check && power < 2) Kit.codeBug();
}
public boolean isEmpty() {
return key
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>Count == 0;
}
public int size() {
return keyCount;
}
public boolean has(Object key) {
if (key == null) { key = UniqueTag.NULL_VALUE; }
return 0 <= findIndex(key);
}
/**
* Get integer value assigned with key.
* @return key integer value or defaultValue if key is absent
*/
public int get(Object key, int defaultValue) {
if (key == null) { key = UniqueTag.NULL_VALUE; }
int index = findIndex(key);
if (0 <= index) {
return values[index];
}
return defaultValue;
}
/**
* Get integer value assigned with key.
* @return key integer value
* @throws RuntimeException if key does not exist
*/
public int getExisting(Object key) {
if (key == null) { key = UniqueTag.NULL_VALUE; }
int index = findIndex(key);
if (0 <= index) {
return values[index];
}
// Key must exist
Kit.codeBug();
return 0;
}
public void put(Object key, int value) {
if (key == null) { key = UniqueTag.NULL_VALUE; }
int index = ensureIndex(key);
values[index] = value;
}
/**
* If table already contains a key that equals to keyArg, return that key
* while setting its value to zero, otherwise add keyArg with 0 value to
* the table and return it.
*/
public Object intern(Object keyArg) {
boolean nullKey = false;
if (keyArg == null) {
nullKey = true;
keyArg = UniqueTag.NULL_VALUE;
}
int index = ensureIndex(keyArg);
values[index] = 0;
return (nullKey) ? null : keys[index];
}
public void remove(Object key) {
if (key == null) { key = UniqueTag.NULL_VALUE; }
int index = findIndex(key);
if (0 <= index) {
keys[index] = DELETED;
--keyCount;
}
}
public void clear() {
int i = keys.length;
while (i != 0) {
keys
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>[--i] = null;
}
keyCount = 0;
occupiedCount = 0;
}
public Iterator newIterator() {
return new Iterator(this);
}
// The sole purpose of the method is to avoid accessing private fields
// from the Iterator inner class to workaround JDK 1.1 compiler bug which
// generates code triggering VerifierError on recent JVMs
final void initIterator(Iterator i) {
i.init(keys, values, keyCount);
}
/** Return array of present keys */
public Object[] getKeys() {
Object[] array = new Object[keyCount];
getKeys(array, 0);
return array;
}
public void getKeys(Object[] array, int offset) {
int count = keyCount;
for (int i = 0; count != 0; ++i) {
Object key = keys[i];
if (key != null && key != DELETED) {
if (key == UniqueTag.NULL_VALUE) { key = null; }
array[offset] = key;
++offset;
--count;
}
}
}
private static int tableLookupStep(int fraction, int mask, int power) {
int shift = 32 - 2 * power;
if (shift >= 0) {
return ((fraction >>> shift) & mask) | 1;
}
else {
return (fraction & (mask >>> -shift)) | 1;
}
}
private int findIndex(Object key) {
if (keys != null) {
int hash = key.hashCode();
int fraction = hash * A;
int index = fraction >>> (32 - power);
Object test = keys[index];
if (test != null) {
int N = 1 << power;
if (test == key
|| (values[N + index] == hash && test.equals(key)))
{
return index;
}
// Search in table after first failed attempt
int mask = N - 1;
int step = tableLookupStep(fraction, mask, power);
int n = 0;
for (;;) {
if (check) {
if (n >= occupiedCount) Kit.codeBug();
++n;
}
index = (index + step) & mask
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>;
test = keys[index];
if (test == null) {
break;
}
if (test == key
|| (values[N + index] == hash && test.equals(key)))
{
return index;
}
}
}
}
return -1;
}
// Insert key that is not present to table without deleted entries
// and enough free space
private int insertNewKey(Object key, int hash) {
if (check && occupiedCount != keyCount) Kit.codeBug();
if (check && keyCount == 1 << power) Kit.codeBug();
int fraction = hash * A;
int index = fraction >>> (32 - power);
int N = 1 << power;
if (keys[index] != null) {
int mask = N - 1;
int step = tableLookupStep(fraction, mask, power);
int firstIndex = index;
do {
if (check && keys[index] == DELETED) Kit.codeBug();
index = (index + step) & mask;
if (check && firstIndex == index) Kit.codeBug();
} while (keys[index] != null);
}
keys[index] = key;
values[N + index] = hash;
++occupiedCount;
++keyCount;
return index;
}
private void rehashTable() {
if (keys == null) {
if (check && keyCount != 0) Kit.codeBug();
if (check && occupiedCount != 0) Kit.codeBug();
int N = 1 << power;
keys = new Object[N];
values = new int[2 * N];
}
else {
// Check if removing deleted entries would free enough space
if (keyCount * 2 >= occupiedCount) {
// Need to grow: less then half of deleted entries
++power;
}
int N = 1 << power;
Object[] oldKeys = keys;
int[] oldValues = values;
int oldN = oldKeys.length;
keys = new Object[N];
values = new int[2 * N];
int remaining = keyCount;
occupiedCount = keyCount = 0;
for (int i = 0; remaining != 0; ++i) {
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS> Object key = oldKeys[i];
if (key != null && key != DELETED) {
int keyHash = oldValues[oldN + i];
int index = insertNewKey(key, keyHash);
values[index] = oldValues[i];
--remaining;
}
}
}
}
// Ensure key index creating one if necessary
private int ensureIndex(Object key) {
int hash = key.hashCode();
int index = -1;
int firstDeleted = -1;
if (keys != null) {
int fraction = hash * A;
index = fraction >>> (32 - power);
Object test = keys[index];
if (test != null) {
int N = 1 << power;
if (test == key
|| (values[N + index] == hash && test.equals(key)))
{
return index;
}
if (test == DELETED) {
firstDeleted = index;
}
// Search in table after first failed attempt
int mask = N - 1;
int step = tableLookupStep(fraction, mask, power);
int n = 0;
for (;;) {
if (check) {
if (n >= occupiedCount) Kit.codeBug();
++n;
}
index = (index + step) & mask;
test = keys[index];
if (test == null) {
break;
}
if (test == key
|| (values[N + index] == hash && test.equals(key)))
{
return index;
}
if (test == DELETED && firstDeleted < 0) {
firstDeleted = index;
}
}
}
}
// Inserting of new key
if (check && keys != null && keys[index] != null)
Kit.codeBug();
if (firstDeleted >= 0) {
index = firstDeleted;
}
else {
// Need to consume empty entry: check occupation level
if (keys == null || occupiedCount * 4 >= (1 << power) * 3) {
// Too litle unused entries: rehash
rehashTable();
return insertNewKey(key, hash);
}
++occupiedCount;
}
keys[index] = key;
values[(1 << power) +
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>/*
* Copyright 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.collect.Lists;
import com.google.javascript.jscomp.CheckLevel;
import java.util.*;
/**
* WarningsGuard that represents just a chain of other guards. For example we
* could have following chain
* 1) all warnings outside of /foo/ should be suppressed
* 2) errors with key JSC_BAR should be marked as warning
* 3) the rest should be reported as error
*
* This class is designed for such behaviour.
*
*
*/
public class ComposeWarningsGuard extends WarningsGuard {
private final List<WarningsGuard> guards;
private static final Comparator<WarningsGuard> guardComparator =
new Comparator<WarningsGuard>() {
@Override
public int compare(WarningsGuard a, WarningsGuard b) {
return a.getPriority() - b.getPriority();
}
};
public ComposeWarningsGuard(List<WarningsGuard> guards) {
this.guards = Lists.newArrayList();
addGuards(guards);
}
public ComposeWarningsGuard(WarningsGuard... guards) {
this(Lists.newArrayList(guards));
}
void addGuard(WarningsGuard guard) {
if (guard instanceof ComposeWarningsGuard) {
addGuards(((ComposeWarningsGuard) guard).guards);
} else {
int index = Collections.binarySearch(this.guards, guard, guardComparator);
if (index < 0) {
index = -index - 1;
}
this.guards.add(index, guard);
}
}
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS> private void addGuards(Iterable<WarningsGuard> guards) {
for (WarningsGuard guard : guards) {
addGuard(guard);
}
}
@Override
public CheckLevel level(JSError error) {
for (WarningsGuard guard : guards) {
CheckLevel newLevel = guard.level(error);
if (newLevel != null) {
return newLevel;
}
}
return null;
}
@Override
public boolean disables(DiagnosticGroup group) {
nextSingleton:
for (DiagnosticType type : group.getTypes()) {
DiagnosticGroup singleton = DiagnosticGroup.forType(type);
for (WarningsGuard guard : guards) {
if (guard.disables(singleton)) {
continue nextSingleton;
} else if (guard.enables(singleton)) {
return false;
}
}
return false;
}
return true;
}
/**
* Determines whether this guard will "elevate" the status of any disabled
* diagnostic type in the group to a warning or an error.
*/
@Override
public boolean enables(DiagnosticGroup group) {
for (WarningsGuard guard : guards) {
if (guard.enables(group)) {
return true;
}
}
return false;
}
List<WarningsGuard> getGuards() {
return Collections.unmodifiableList(guards);
}
}
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>();
// Save the tree for later comparison.
Node rootClone = root.cloneTree();
Node externsRootClone = rootClone.getFirstChild();
Node mainRootClone = rootClone.getLastChild();
int numRepetitions = getNumRepetitions();
ErrorManager[] errorManagers = new ErrorManager[numRepetitions];
int aggregateWarningCount = 0;
List<JSError> aggregateWarnings = Lists.newArrayList();
boolean hasCodeChanged = false;
assertFalse("Code should not change before processing",
recentChange.hasCodeChanged());
for (int i = 0; i < numRepetitions; ++i) {
if (compiler.getErrorCount() == 0) {
errorManagers[i] = new BlackHoleErrorManager(compiler);
// Only run the type checking pass once, if asked.
// Running it twice can cause unpredictable behavior because duplicate
// objects for the same type are created, and the type system
// uses reference equality to compare many types.
if (typeCheckEnabled && i == 0) {
TypeCheck check = createTypeCheck(compiler, typeCheckLevel);
check.processForTesting(externsRoot, mainRoot);
}
// Only run the normalize pass once, if asked.
if (normalizeEnabled && i == 0) {
Normalize normalize = new Normalize(compiler, false);
normalize.process(externsRoot, mainRoot);
compiler.setNormalized();
}
if (markNoSideEffects && i == 0) {
MarkNoSideEffectCalls mark = new MarkNoSideEffectCalls(compiler);
mark.process(externsRoot, mainRoot);
}
recentChange.reset();
getProcessor(compiler).process(externsRoot, mainRoot);
if (checkLineNumbers) {
(new LineNumberCheck(compiler)).process(externsRoot, mainRoot);
}
hasCodeChanged = hasCodeChanged || recentChange.hasCodeChanged();
aggregateWarningCount += errorManagers[i].getWarningCount();
aggregateWarnings.addAll(Lists.newArrayList(compiler.getWarnings()));
if (normalizeEnabled) {
boolean verifyDeclaredConstants = true;
new Normalize.VerifyConstants(compiler, verifyDeclaredConstants)
.process(externsRoot, mainRoot);
}
}
}
if (error == null) {
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS> */
static JSModule[] createModules(String... inputs) {
JSModule[] modules = new JSModule[inputs.length];
for (int i = 0; i < inputs.length; i++) {
JSModule module = modules[i] = new JSModule("m" + i);
module.add(JSSourceFile.fromCode("i" + i, inputs[i]));
}
return modules;
}
private static class BlackHoleErrorManager extends BasicErrorManager {
private BlackHoleErrorManager(Compiler compiler) {
compiler.setErrorManager(this);
}
@Override
public void println(CheckLevel level, JSError error) {}
@Override
public void printSummary() {}
}
private Compiler createCompiler() {
Compiler compiler = new Compiler();
return compiler;
}
protected void setExpectedSymbolTableError(DiagnosticType type) {
this.expectedSymbolTableError = type;
}
}
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>/*
* Copyright 2007 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.collect.Sets;
import com.google.javascript.jscomp.CheckLevel;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.SortedSet;
/**
* <p>A basic error manager that sorts all errors and warnings reported to it to
* generate a sorted report when the {@link #generateReport()} method
* is called.</p>
*
* <p>This error manager does not produce any output, but subclasses can
* override the {@link #println(CheckLevel, JSError)} method to generate custom
* output.</p>
*
*
*
*/
public abstract class BasicErrorManager implements ErrorManager {
private final SortedSet<ErrorWithLevel> messages =
Sets.newTreeSet(new LeveledJSErrorComparator());
private int errorCount = 0;
private int warningCount = 0;
private double typedPercent = 0.0;
public void report(CheckLevel level, JSError error) {
if (messages.add(new ErrorWithLevel(error, level))) {
if (level == CheckLevel.ERROR) {
errorCount++;
} else if (level == CheckLevel.WARNING) {
warningCount++;
}
}
}
public void generateReport() {
for (ErrorWithLevel message : messages) {
println(message.level, message.error);
}
printSummary();
}
/**
* Print a message with a trailing new line. This method is called by the
* {@link #generate
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>Report()} method when generating messages.
*/
public abstract void println(CheckLevel level, JSError error);
/**
* Print the summary of the compilation - number of errors and warnings.
*/
protected abstract void printSummary();
public int getErrorCount() {
return errorCount;
}
public int getWarningCount() {
return warningCount;
}
public JSError[] getErrors() {
return toArray(CheckLevel.ERROR);
}
public JSError[] getWarnings() {
return toArray(CheckLevel.WARNING);
}
public void setTypedPercent(double typedPercent) {
this.typedPercent = typedPercent;
}
public double getTypedPercent() {
return typedPercent;
}
private JSError[] toArray(CheckLevel level) {
List<JSError> errors = new ArrayList<JSError>(messages.size());
for (ErrorWithLevel p : messages) {
if (p.level == level) {
errors.add(p.error);
}
}
return errors.toArray(new JSError[errors.size()]);
}
/**
* <p>Comparator of {@link JSError} with an associated {@link CheckLevel}.
* The ordering is the standard lexical ordering on the quintuple
* (file name, line number, {@link CheckLevel},
* character number, description).</p>
*
* <p>Note: this comparator imposes orderings that are inconsistent with
* {@link JSError#equals(Object)}.</p>
*/
static final class LeveledJSErrorComparator
implements Comparator<ErrorWithLevel> {
private static final int P1_LT_P2 = -1;
private static final int P1_GT_P2 = 1;
public int compare(ErrorWithLevel p1, ErrorWithLevel p2) {
// null is the smallest value
if (p2 == null) {
if (p1 == null) {
return 0;
} else {
return P1_GT_P2;
}
}
// check level
if (p1.level != p2.level) {
return p2.level.compareTo(p1.level);
}
// sourceName comparison
String source1 = p1.error.sourceName;
String source2
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>int i = 0; i != N; ++i) {
Object current = getImpl(i);
if (current == obj || (current != null && current.equals(obj))) {
return i;
}
}
return -1;
}
public int lastIndexOf(Object obj)
{
for (int i = size; i != 0;) {
--i;
Object current = getImpl(i);
if (current == obj || (current != null && current.equals(obj))) {
return i;
}
}
return -1;
}
public final Object peek()
{
int N = size;
if (N == 0) throw onEmptyStackTopRead();
return getImpl(N - 1);
}
@SuppressWarnings("fallthrough")
public final Object pop()
{
if (sealed) throw onSeledMutation();
int N = size;
--N;
Object top;
switch (N) {
case -1: throw onEmptyStackTopRead();
case 0: top = f0; f0 = null; break;
case 1: top = f1; f1 = null; break;
case 2: top = f2; f2 = null; break;
case 3: top = f3; f3 = null; break;
case 4: top = f4; f4 = null; break;
default:
top = data[N - FIELDS_STORE_SIZE];
data[N - FIELDS_STORE_SIZE] = null;
}
size = N;
return top;
}
public final void push(Object value)
{
add(value);
}
public final void add(Object value)
{
if (sealed) throw onSeledMutation();
int N = size;
if (N >= FIELDS_STORE_SIZE) {
ensureCapacity(N + 1);
}
size = N + 1;
setImpl(N, value);
}
@SuppressWarnings("fallthrough")
public final void add(int index, Object value)
{
int N = size;
if (!(0 <= index && index <= N)) throw onInvalidIndex(index, N + 1);
if (sealed) throw onSeledMutation();
Object
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS> tmp;
switch (index) {
case 0:
if (N == 0) { f0 = value; break; }
tmp = f0; f0 = value; value = tmp;
case 1:
if (N == 1) { f1 = value; break; }
tmp = f1; f1 = value; value = tmp;
case 2:
if (N == 2) { f2 = value; break; }
tmp = f2; f2 = value; value = tmp;
case 3:
if (N == 3) { f3 = value; break; }
tmp = f3; f3 = value; value = tmp;
case 4:
if (N == 4) { f4 = value; break; }
tmp = f4; f4 = value; value = tmp;
index = FIELDS_STORE_SIZE;
default:
ensureCapacity(N + 1);
if (index != N) {
System.arraycopy(data, index - FIELDS_STORE_SIZE,
data, index - FIELDS_STORE_SIZE + 1,
N - index);
}
data[index - FIELDS_STORE_SIZE] = value;
}
size = N + 1;
}
@SuppressWarnings("fallthrough")
public final void remove(int index)
{
int N = size;
if (!(0 <= index && index < N)) throw onInvalidIndex(index, N);
if (sealed) throw onSeledMutation();
--N;
switch (index) {
case 0:
if (N == 0) { f0 = null; break; }
f0 = f1;
case 1:
if (N == 1) { f1 = null; break; }
f1 = f2;
case 2:
if (N == 2) { f2 = null; break; }
f2 = f3;
case 3:
if (N == 3) { f3 = null; break; }
f3 = f4;
case 4:
if (N == 4) { f4 = null; break; }
f4 = data[0];
index = FIELDS_STORE_SIZE;
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>Native.
private final boolean isChecked;
UnknownType(JSTypeRegistry registry, boolean isChecked) {
super(registry);
this.isChecked = isChecked;
}
@Override
public boolean isUnknownType() {
return true;
}
@Override
public boolean isCheckedUnknownType() {
return isChecked;
}
@Override
public boolean canAssignTo(JSType that) {
return true;
}
@Override
public boolean canBeCalled() {
return true;
}
@Override
public boolean matchesNumberContext() {
return true;
}
@Override
public boolean matchesObjectContext() {
return true;
}
@Override
public boolean matchesStringContext() {
return true;
}
@Override
public TernaryValue testForEquality(JSType that) {
return UNKNOWN;
}
@Override
public boolean isNullable() {
return true;
}
@Override
public boolean isSubtype(JSType that) {
return true;
}
@Override
public JSType getLeastSupertype(JSType that) {
return this;
}
@Override
public JSType getGreatestSubtype(JSType that) {
return this;
}
@Override
public <T> T visit(Visitor<T> visitor) {
return visitor.caseUnknownType();
}
@Override
public String toString() {
return getReferenceName();
}
@Override
boolean defineProperty(String propertyName, JSType type,
boolean inferred, boolean inExterns) {
// nothing to define
return true;
}
@Override
public ObjectType getImplicitPrototype() {
return null;
}
@Override
public int getPropertiesCount() {
return Integer.MAX_VALUE;
}
@Override
protected void collectPropertyNames(Set<String> props) {
}
@Override
public JSType getPropertyType(String propertyName) {
return this;
}
@Override
public boolean hasProperty(String propertyName) {
return true;
}
@Override
public FunctionType getConstructor() {
return null;
}
@Override
public String getReferenceName() {
return isChecked ? "??" : "?";
}
@Override
public boolean isPropertyTypeDeclared(String propertyName) {
return false;
}
@
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>/*
* Copyright 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.collect.Iterables;
import com.google.common.collect.LinkedHashMultimap;
import com.google.common.collect.Maps;
import com.google.common.collect.Multimap;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
/**
* A {@link JSModule} dependency graph that assigns a depth to each module and
* can answer depth-related queries about them. For the purposes of this class,
* a module's depth is defined as the number of hops in the longest path from
* the module to a module with no dependencies.
*
*
*/
public class JSModuleGraph {
/**
* Map from a module to its depth.
*/
private Map<JSModule, Integer> moduleDepths;
/**
* Lists of modules at each depth. <code>modulesByDepth.get(3)</code> is a
* list of the modules at depth 3, for example.
*/
private List<List<JSModule>> modulesByDepth;
/**
* dependencyMap is a cache of dependencies that makes the dependsOn
* function faster. Each map entry associates a starting
* JSModule with the set of JSModules that are transitively dependent on the
* starting module.
*
* If the cache returns null, then the entry hasn
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>'t been filled in for that
* module.
*
* dependencyMap should be filled from leaf to root so that
* getTransitiveDepsDeepestFirst can use its results directly.
*/
private Map<JSModule, Set<JSModule>> dependencyMap = Maps.newHashMap();
/**
* Creates a module graph from a list of modules in dependency order.
*/
public JSModuleGraph(JSModule[] modulesInDepOrder) {
moduleDepths = new HashMap<JSModule, Integer>(modulesInDepOrder.length);
modulesByDepth = new ArrayList<List<JSModule>>();
for (JSModule module : modulesInDepOrder) {
int depth = 0;
for (JSModule dep : module.getDependencies()) {
Integer depDepth = moduleDepths.get(dep);
if (depDepth == null) {
throw new ModuleDependenceException(String.format(
"Modules not in dependency order: %s preceded %s",
module.getName(), dep.getName()),
module, dep);
}
depth = Math.max(depth, depDepth + 1);
}
moduleDepths.put(module, depth);
if (depth == modulesByDepth.size()) {
modulesByDepth.add(new ArrayList<JSModule>());
}
modulesByDepth.get(depth).add(module);
}
}
/**
* Gets an iterable over all modules.
*/
Iterable<JSModule> getAllModules() {
return moduleDepths.keySet();
}
/**
* Gets the total number of modules.
*/
int getModuleCount() {
return moduleDepths.size();
}
/**
* Gets the root module.
*/
JSModule getRootModule() {
return Iterables.getOnlyElement(modulesByDepth.get(0));
}
/**
* Gets the depth of a module.
*
* @param module A module in this graph
* @return The depth of the module
*/
int getDepth(JSModule module) {
return moduleDepths.get(module);
}
/**
* Determines whether this module depends on a given module. Note that a
* module never depends on itself, as that dependency would be cyclic.
*/
public boolean dependsOn(JSModule src, JSModule m) {
Set
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS><JSModule> deps = dependencyMap.get(src);
if (deps == null) {
deps = getTransitiveDepsDeepestFirst(src);
dependencyMap.put(src, deps);
}
return deps.contains(m);
}
/**
* Finds the deepest common dependency of two modules, not including the two
* modules themselves.
*
* @param m1 A module in this graph
* @param m2 A module in this graph
* @return The deepest common dep of {@code m1} and {@code m2}, or null if
* they have no common dependencies
*/
JSModule getDeepestCommonDependency(JSModule m1, JSModule m2) {
int m1Depth = getDepth(m1);
int m2Depth = getDepth(m2);
// According our definition of depth, the result must have a strictly
// smaller depth than either m1 or m2.
for (int depth = Math.min(m1Depth, m2Depth) - 1; depth >= 0; depth--) {
List<JSModule> modulesAtDepth = modulesByDepth.get(depth);
// Look at the modules at this depth in reverse order, so that we use the
// original ordering of the modules to break ties (later meaning deeper).
for (int i = modulesAtDepth.size() - 1; i >= 0; i--) {
JSModule m = modulesAtDepth.get(i);
if (dependsOn(m1, m) && dependsOn(m2, m)) {
return m;
}
}
}
return null;
}
/**
* Finds the deepest common dependency of two modules, including the
* modules themselves.
*
* @param m1 A module in this graph
* @param m2 A module in this graph
* @return The deepest common dep of {@code m1} and {@code m2}, or null if
* they have no common dependencies
*/
public JSModule getDeepestCommonDependencyInclusive(
JSModule m1, JSModule m2) {
if (m2 == m1 || dependsOn(m2, m1)) {
return m1;
} else if (dependsOn(m1, m2
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>)) {
return m2;
}
return getDeepestCommonDependency(m1, m2);
}
/** Returns the deepest common dependency of the given modules. */
public JSModule getDeepestCommonDependencyInclusive(
Collection<JSModule> modules) {
Iterator<JSModule> iter = modules.iterator();
JSModule dep = iter.next();
while (iter.hasNext()) {
dep = getDeepestCommonDependencyInclusive(dep, iter.next());
}
return dep;
}
/**
* Creates an iterable over the transitive dependencies of module {@code m}
* in a non-increasing depth ordering. The result does not include the module
* {@code m}.
*
* @param m A module in this graph
* @return The transitive dependencies of module {@code m}
*/
Set<JSModule> getTransitiveDepsDeepestFirst(JSModule m) {
Set<JSModule> deps = dependencyMap.get(m);
if (deps != null) {
return deps;
}
deps = new TreeSet<JSModule>(new InverseDepthComparator());
addDeps(deps, m);
dependencyMap.put(m, deps);
return deps;
}
/**
* Adds a module's transitive dependencies to a set.
*/
private void addDeps(Set<JSModule> deps, JSModule m) {
for (JSModule dep : m.getDependencies()) {
deps.add(dep);
addDeps(deps, dep);
}
}
/**
* Replaces any files that are found multiple times with a single instance in
* the closest parent module that is common to all modules where it appears.
*
* JSCompiler normally errors if you attempt to compile modules containing the
* same file. This method can be used to remove duplicates before compiling
* to avoid such an error.
*/
public void coalesceDuplicateFiles() {
Multimap<String, JSModule> fileRefs = LinkedHashMultimap.create();
for (JSModule module : moduleDepths.keySet()) {
for (CompilerInput jsFile : module.getInputs()) {
fileRefs.put(jsFile.getName(), module);
}
}
for (String path : fileRefs.keySet()) {
Collection<JSModule> ref
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>Modules = fileRefs.get(path);
if (refModules.size() > 1) {
JSModule depModule = getDeepestCommonDependencyInclusive(refModules);
CompilerInput file = refModules.iterator().next().getByName(path);
for (JSModule module : refModules) {
if (module != depModule) {
module.removeByName(path);
}
}
if (!refModules.contains(depModule)) {
depModule.add(file);
}
}
}
}
/**
* A module depth comparator that considers a deeper module to be "less than"
* a shallower module. Uses module names to consistently break ties.
*/
private class InverseDepthComparator implements Comparator<JSModule> {
public int compare(JSModule m1, JSModule m2) {
if (m1 == m2) {
return 0;
}
int d1 = getDepth(m1);
int d2 = getDepth(m2);
return d2 < d1 ? -1 : d2 == d1 ? m2.getName().compareTo(m1.getName()) : 1;
}
}
/*
* Exception class for declaring when the modules being fed into a
* JSModuleGraph as input aren't in dependence order, and so can't be
* processed for caching of various dependency-related queries.
*/
protected static class ModuleDependenceException
extends IllegalArgumentException {
private static final long serialVersionUID = 1;
private final JSModule module;
private final JSModule dependentModule;
protected ModuleDependenceException(String message,
JSModule module, JSModule dependentModule) {
super(message);
this.module = module;
this.dependentModule = dependentModule;
}
public JSModule getModule() {
return module;
}
public JSModule getDependentModule() {
return dependentModule;
}
}
}
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>IN_EXTERNS_ERROR =
DiagnosticType.warning(
"JSC_NAME_REFERENCE_IN_EXTERNS",
"accessing name {0} in externs has no effect");
static final DiagnosticType INVALID_FUNCTION_DECL =
DiagnosticType.error("JSC_INVALID_FUNCTION_DECL",
"Syntax error: function declaration must have a name");
private CompilerInput synthesizedExternsInput = null;
private Node synthesizedExternsRoot = null;
private final AbstractCompiler compiler;
// Whether this is the post-processing sanity check.
private final boolean sanityCheck;
VarCheck(AbstractCompiler compiler) {
this(compiler, false);
}
VarCheck(AbstractCompiler compiler, boolean sanityCheck) {
this.compiler = compiler;
this.sanityCheck = sanityCheck;
}
/** {@inheritDoc} */
public void process(Node externs, Node root) {
NodeTraversal.traverse(compiler, externs, new NameRefInExternsCheck());
NodeTraversal.traverseRoots(
compiler, Lists.newArrayList(externs, root), this);
}
/** {@inheritDoc} */
public void visit(NodeTraversal t, Node n, Node parent) {
if (n.getType() != Token.NAME) {
return;
}
if (NodeUtil.isLabelName(n)) {
return;
}
String varName = n.getString();
// Only a function can have an empty name.
if (varName.isEmpty()) {
Preconditions.checkState(NodeUtil.isFunction(parent));
// A function declaration with an empty name passes Rhino,
// but is supposed to be a syntax error according to the spec.
if (!NodeUtil.isAnonymousFunction(parent)) {
t.report(n, INVALID_FUNCTION_DECL);
}
return;
}
// Check that the var has been declared.
Scope scope = t.getScope();
Scope.Var var = scope.getVar(varName);
if (var == null) {
if (NodeUtil.isAnonymousFunction(parent)) {
// e.g. [ function foo() {} ], it's okay if "foo" isn't defined in the
// current scope.
} else {
t.report(n, UNDEFINED_VAR_ERROR, varName);
if
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS> (sanityCheck) {
throw new IllegalStateException("Unexpected variable " + varName);
} else {
// Create a new variable in a synthetic script. This will prevent
// subsequent compiler passes from crashing.
Node nameNode = Node.newString(Token.NAME, varName);
getSynthesizedExternsRoot().addChildToBack(
new Node(Token.VAR, nameNode));
scope.getGlobalScope().declare(varName, nameNode,
null, getSynthesizedExternsInput());
}
}
return;
}
CompilerInput currInput = t.getInput();
CompilerInput varInput = var.input;
if (currInput == varInput || currInput == null || varInput == null) {
// The variable was defined in the same file. This is fine.
return;
}
// Check module dependencies.
JSModule currModule = currInput.getModule();
JSModule varModule = varInput.getModule();
JSModuleGraph moduleGraph = compiler.getModuleGraph();
if (varModule != currModule && varModule != null && currModule != null) {
if (moduleGraph.dependsOn(currModule, varModule)) {
// The module dependency was properly declared.
} else {
if (!sanityCheck && scope.isGlobal()) {
if (moduleGraph.dependsOn(varModule, currModule)) {
// The variable reference violates a declared module dependency.
t.report(n, VIOLATED_MODULE_DEP_ERROR,
currModule.getName(), varModule.getName(), varName);
} else {
// The variable reference is between two modules that have no
// dependency relationship. This should probably be considered an
// error, but just issue a warning for now.
t.report(n, MISSING_MODULE_DEP_ERROR,
currModule.getName(), varModule.getName(), varName);
}
} else {
t.report(n, STRICT_MODULE_DEP_ERROR,
currModule.getName(), varModule.getName(), varName);
}
}
}
}
/**
* A check for name references in the externs inputs. These used to prevent
* a variable from getting renamed, but no longer have any effect.
*/
private class NameRefInExternsCheck extends AbstractPostOrderCallback {
public void visit(
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS> {
private static final long serialVersionUID = 1L;
VoidType(JSTypeRegistry registry) {
super(registry);
}
@Override
public JSType restrictByNotNullOrUndefined() {
return registry.getNativeType(JSTypeNative.NO_TYPE);
}
@Override
public TernaryValue testForEquality(JSType that) {
if (UNKNOWN.equals(super.testForEquality(that))) {
return UNKNOWN;
}
if (that.isSubtype(this) ||
that.isSubtype(getNativeType(JSTypeNative.NULL_TYPE))) {
return TRUE;
}
return FALSE;
}
@Override
public boolean matchesNumberContext() {
return false;
}
@Override
public boolean matchesObjectContext() {
return false;
}
@Override
public boolean matchesStringContext() {
return true;
}
@Override
public boolean isVoidType() {
return true;
}
@Override
public String toString() {
return "undefined";
}
@Override
public BooleanLiteralSet getPossibleToBooleanOutcomes() {
return BooleanLiteralSet.FALSE;
}
@Override
public <T> T visit(Visitor<T> visitor) {
return visitor.caseVoidType();
}
}
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>/*
* Copyright 2005 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* A JavaScript module has a unique name, consists of a list of compiler inputs,
* and can depend on other modules.
*
*
*
*/
public class JSModule {
/** Module name */
private final String name;
/** Source code inputs */
private final List<CompilerInput> inputs = new ArrayList<CompilerInput>();
/** Modules that this module depends on */
private final List<JSModule> deps = new ArrayList<JSModule>();
/**
* Creates an instance.
*
* @param name A unique name for the module
*/
public JSModule(String name) {
this.name = name;
}
/** Gets the module name. */
public String getName() {
return name;
}
/** Adds a source file input to this module. */
public void add(JSSourceFile file) {
add(new CompilerInput(file));
}
/** Adds a source file input to this module. */
public void addFirst(JSSourceFile file) {
addFirst(new CompilerInput(file));
}
/** Adds a source code input to this module. */
public void add(CompilerInput input) {
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>
inputs.add(input);
input.setModule(this);
}
/** Adds a source code input to this module. */
public void addFirst(CompilerInput input) {
inputs.add(0, input);
input.setModule(this);
}
/** Adds a source code input to this module directly after other. */
public void addAfter(CompilerInput input, CompilerInput other) {
Preconditions.checkState(inputs.contains(other));
inputs.add(inputs.indexOf(other), input);
input.setModule(this);
}
/** Adds a dependency on another module. */
public void addDependency(JSModule dep) {
Preconditions.checkState(dep != this);
deps.add(dep);
}
/** Removes all of the inputs from this module. */
public void removeAll() {
for (CompilerInput input : inputs) {
input.setModule(null);
}
inputs.clear();
}
/**
* Gets the list of modules that this module depends on.
*
* @return A list that may be empty but not null
*/
public List<JSModule> getDependencies() {
return deps;
}
/**
* Returns the transitive closure of dependencies starting from the
* dependencies of this module.
*/
public Set<JSModule> getAllDependencies() {
Set<JSModule> allDeps = Sets.newHashSet(deps);
List<JSModule> workList = Lists.newArrayList(deps);
while (workList.size() > 0) {
JSModule module = workList.remove(workList.size() - 1);
for (JSModule dep : module.getDependencies()) {
if (allDeps.add(dep)) {
workList.add(dep);
}
}
}
return allDeps;
}
/** Returns this module and all of its dependencies in one list. */
public Set<JSModule> getThisAndAllDependencies() {
Set<JSModule> deps = getAllDependencies();
deps.add(this);
return deps;
}
/**
* Gets this module's list of source code inputs.
*
* @return A list that may be empty but not null
*/
public List<CompilerInput> getInputs() {
return inputs;
}
/** Returns the input with the
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS> given name or null if none. */
public CompilerInput getByName(String name) {
for (CompilerInput input : inputs) {
if (name.equals(input.getName())) {
return input;
}
}
return null;
}
/**
* Removes any input with the given name. Returns whether any were removed.
*/
public boolean removeByName(String name) {
boolean found = false;
Iterator<CompilerInput> iter = inputs.iterator();
while (iter.hasNext()) {
CompilerInput file = iter.next();
if (name.equals(file.getName())) {
iter.remove();
file.setModule(null);
found = true;
}
}
return found;
}
/** Returns the module name (primarily for debugging). */
@Override
public String toString() {
return name;
}
/**
* Removes any references to nodes of the AST. This method is needed to
* allow the ASTs to be garbage collected if the modules are kept around.
*/
public void clearAsts() {
for (CompilerInput input : inputs) {
input.clearAst();
}
}
/**
* Puts the JS files into a topologically sorted order by their dependencies.
*/
public void sortInputsByDeps(Compiler compiler) {
// Collect all symbols provided in these files.
final Map<String, CompilerInput> provides = Maps.newHashMap();
for (CompilerInput input : inputs) {
for (String provide : input.getProvides(compiler)) {
provides.put(provide, input);
}
}
// Put the files into topologically sorted order by their requires.
// NOTE: This will leave the list unchanged if the files are already
// topologically sorted. This is important to apps whose dependencies
// are incomplete.
List<CompilerInput> list = Lists.newArrayList();
Set<CompilerInput> set = Sets.newHashSet();
for (CompilerInput input : inputs) {
addInputAndDeps(input, provides, compiler, list, set,
Sets.<CompilerInput>newHashSet());
}
// Update the JSModule to this order.
Preconditions.checkState(inputs.size() == list.size());
inputs.clear();
inputs.addAll(list);
}
/**
*
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS> Returns the given collection of modules in topological order.
*
* Note that this will return the modules in the same order if they are
* already sorted, and in general, will only change the order as necessary to
* satisfy the ordering dependencies. This can be important for cases where
* the modules do not properly specify all dependencies.
*/
public static JSModule[] sortJsModules(Collection<JSModule> modules) {
List<JSModule> list = Lists.newArrayList();
Set<JSModule> set = Sets.newHashSet();
for (JSModule module : modules) {
addModuleAndDeps(module, list, set, Sets.<JSModule>newHashSet());
}
return list.toArray(new JSModule[list.size()]);
}
/**
* Adds the given input and its deps to the given list and set, if they are
* not already added, placing dependencies before dependants.
*/
private static void addInputAndDeps(
CompilerInput input, Map<String, CompilerInput> provides,
Compiler compiler, List<CompilerInput> list, Set<CompilerInput> set,
Set<CompilerInput> inProgress) {
if (!set.contains(input)) {
if (inProgress.contains(input)) {
throw new IllegalArgumentException(
"Circular dependency involving input: " + input.getName());
}
inProgress.add(input);
for (String require : input.getRequires(compiler)) {
if (provides.containsKey(require)) {
addInputAndDeps(provides.get(require), provides, compiler, list, set,
inProgress);
}
}
list.add(input);
set.add(input);
}
}
/**
* Adds the given module and its deps to the given list and set, if they are
* not already added, placing dependencies before dependants.
*/
private static void addModuleAndDeps(
JSModule module, List<JSModule> list, Set<JSModule> set,
Set<JSModule> inProgress) {
if (!set.contains(module)) {
if (inProgress.contains(module)) {
throw new IllegalArgumentException(
"Circular dependency involving module: " + module.getName());
}
inProgress.add(module);
for (JSModule dep : module.getDependencies()) {
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>
addModuleAndDeps(dep, list, set, inProgress);
}
list.add(module);
set.add(module);
}
}
}
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS> qualifiedName = node.getQualifiedName();
Preconditions.checkNotNull(qualifiedName);
JSType origType = node.getJSType();
origType = origType == null ? getNativeType(UNKNOWN_TYPE) : origType;
scope.inferQualifiedSlot(qualifiedName, origType, type);
break;
default:
throw new IllegalArgumentException("Node cannot be refined.");
}
}
/**
* @see #getRestrictedWithoutUndefined(JSType)
*/
private final Visitor<JSType> restrictUndefinedVisitor =
new Visitor<JSType>() {
public JSType caseEnumElementType(EnumElementType enumElementType) {
JSType type = enumElementType.getPrimitiveType().visit(this);
if (type != null && enumElementType.getPrimitiveType().equals(type)) {
return enumElementType;
} else {
return type;
}
}
public JSType caseAllType() {
return typeRegistry.createUnionType(OBJECT_TYPE, NUMBER_TYPE,
STRING_TYPE, BOOLEAN_TYPE, NULL_TYPE);
}
public JSType caseNoObjectType() {
return getNativeType(NO_OBJECT_TYPE);
}
public JSType caseNoType() {
return getNativeType(NO_TYPE);
}
public JSType caseBooleanType() {
return getNativeType(BOOLEAN_TYPE);
}
public JSType caseFunctionType(FunctionType type) {
return type;
}
public JSType caseNullType() {
return getNativeType(NULL_TYPE);
}
public JSType caseNumberType() {
return getNativeType(NUMBER_TYPE);
}
public JSType caseObjectType(ObjectType type) {
return type;
}
public JSType caseStringType() {
return getNativeType(STRING_TYPE);
}
public JSType caseUnionType(UnionType type) {
return type.getRestrictedUnion(getNativeType(VOID_TYPE));
}
public JSType caseUnknownType() {
return getNativeType(UNKNOWN_TYPE);
}
public JSType caseVoidType() {
return null;
}
};
/**
* @see #getRestrictedWithoutNull(JSType)
*/
private final Visitor<JSType> restrictNullVisitor =
new Visitor<JSType>() {
public JSType caseEnumElementType(EnumElementType enumElementType)
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS> {
JSType type = enumElementType.getPrimitiveType().visit(this);
if (type != null && enumElementType.getPrimitiveType().equals(type)) {
return enumElementType;
} else {
return type;
}
}
public JSType caseAllType() {
return typeRegistry.createUnionType(OBJECT_TYPE, NUMBER_TYPE,
STRING_TYPE, BOOLEAN_TYPE, VOID_TYPE);
}
public JSType caseNoObjectType() {
return getNativeType(NO_OBJECT_TYPE);
}
public JSType caseNoType() {
return getNativeType(NO_TYPE);
}
public JSType caseBooleanType() {
return getNativeType(BOOLEAN_TYPE);
}
public JSType caseFunctionType(FunctionType type) {
return type;
}
public JSType caseNullType() {
return null;
}
public JSType caseNumberType() {
return getNativeType(NUMBER_TYPE);
}
public JSType caseObjectType(ObjectType type) {
return type;
}
public JSType caseStringType() {
return getNativeType(STRING_TYPE);
}
public JSType caseUnionType(UnionType type) {
return type.getRestrictedUnion(getNativeType(NULL_TYPE));
}
public JSType caseUnknownType() {
return getNativeType(UNKNOWN_TYPE);
}
public JSType caseVoidType() {
return getNativeType(VOID_TYPE);
}
};
/**
* A class common to all visitors that need to restrict the type based on
* {@code typeof}-like conditions.
*/
abstract class RestrictByTypeOfResultVisitor
implements Visitor<JSType> {
/**
* Abstracts away the similarities between visiting the unknown type and the
* all type.
* @param topType {@code UNKNOWN_TYPE} or {@code ALL_TYPE}
* @return the restricted type
* @see #caseAllType
* @see #caseUnknownType
*/
protected abstract JSType caseTopType(JSType topType);
public JSType caseAllType() {
return caseTopType(getNativeType(ALL_TYPE));
}
public JSType caseUnknownType() {
return caseTopType(getNativeType(UNKNOWN_TYPE));
}
public JSType caseUnionType
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>(UnionType type) {
JSType restricted = null;
for (JSType alternate : type.getAlternates()) {
JSType restrictedAlternate = alternate.visit(this);
if (restrictedAlternate != null) {
if (restricted == null) {
restricted = restrictedAlternate;
} else {
restricted = restrictedAlternate.getLeastSupertype(restricted);
}
}
}
return restricted;
}
public JSType caseNoType() {
return getNativeType(NO_TYPE);
}
public JSType caseEnumElementType(EnumElementType enumElementType) {
// NOTE(nicksantos): This is a white lie. Suppose we have:
// /** @enum {string|number} */ var MyEnum = ...;
// if (goog.isNumber(myEnumInstance)) {
// /* what is myEnumInstance here? */
// }
// There is no type that represents {MyEnum - string}. What we really
// need is a notion of "enum subtyping", so that we could dynamically
// create a subtype of MyEnum restricted by string. In any case,
// this should catch the common case.
JSType type = enumElementType.getPrimitiveType().visit(this);
if (type != null && enumElementType.getPrimitiveType().equals(type)) {
return enumElementType;
} else {
return type;
}
}
}
/**
* A class common to all visitors that need to restrict the type based on
* some {@code typeof}-like condition being true. All base cases return
* {@code null}. It is up to the subclasses to override the appropriate ones.
*/
abstract class RestrictByTrueTypeOfResultVisitor
extends RestrictByTypeOfResultVisitor {
public JSType caseNoObjectType() {
return null;
}
public JSType caseBooleanType() {
return null;
}
public JSType caseFunctionType(FunctionType type) {
return null;
}
public JSType caseNullType() {
return null;
}
public JSType caseNumberType() {
return null;
}
public JSType caseObjectType(ObjectType type) {
return null;
}
public JSType caseStringType() {
return null;
}
public JSType caseVoidType() {
return null;
}
}
/**
* A
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS> class common to all visitors that need to restrict the type based on
* some {@code typeof}-like condition being false. All base cases return
* their type. It is up to the subclasses to override the appropriate ones.
*/
abstract class RestrictByFalseTypeOfResultVisitor
extends RestrictByTypeOfResultVisitor {
@Override
protected JSType caseTopType(JSType topType) {
return topType;
}
public JSType caseNoObjectType() {
return getNativeType(NO_OBJECT_TYPE);
}
public JSType caseBooleanType() {
return getNativeType(BOOLEAN_TYPE);
}
public JSType caseFunctionType(FunctionType type) {
return type;
}
public JSType caseNullType() {
return getNativeType(NULL_TYPE);
}
public JSType caseNumberType() {
return getNativeType(NUMBER_TYPE);
}
public JSType caseObjectType(ObjectType type) {
return type;
}
public JSType caseStringType() {
return getNativeType(STRING_TYPE);
}
public JSType caseVoidType() {
return getNativeType(VOID_TYPE);
}
}
/**
* @see ChainableReverseAbstractInterpreter#getRestrictedByTypeOfResult
*/
private class RestrictByOneTypeOfResultVisitor
extends RestrictByTypeOfResultVisitor {
/**
* A value known to be equal or not equal to the result of the
* {@code typeOf} operation.
*/
private final String value;
/**
* {@code true} if the {@code typeOf} result is known to equal
* {@code value}; {@code false} if it is known <em>not</em> to equal
* {@code value}.
*/
private final boolean resultEqualsValue;
RestrictByOneTypeOfResultVisitor(String value, boolean resultEqualsValue) {
this.value = value;
this.resultEqualsValue = resultEqualsValue;
}
/**
* Computes whether the given result of a {@code typeof} operator matches
* expectations, i.e. whether a type that gives such a result should be
* kept.
*/
private boolean matchesExpectation(String result) {
return result.equals(value) == resultEqualsValue;
}
@Override
protected JSType caseTopType(JSType topType) {
if (
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>resultEqualsValue) {
if (value.equals("number")) {
return getNativeType(NUMBER_TYPE);
} else if (value.equals("boolean")) {
return getNativeType(BOOLEAN_TYPE);
} else if (value.equals("string")) {
return getNativeType(STRING_TYPE);
} else if (value.equals("undefined")) {
return getNativeType(VOID_TYPE);
} else if (value.equals("function")) {
return getNativeType(U2U_CONSTRUCTOR_TYPE);
}
}
return topType;
}
public JSType caseNoObjectType() {
return (value.equals("object") || value.equals("function")) ==
resultEqualsValue ? getNativeType(NO_OBJECT_TYPE) : null;
}
public JSType caseBooleanType() {
return matchesExpectation("boolean") ? getNativeType(BOOLEAN_TYPE) : null;
}
public JSType caseFunctionType(FunctionType type) {
return matchesExpectation("function") ? type : null;
}
public JSType caseNullType() {
return matchesExpectation("object") ? getNativeType(NULL_TYPE) : null;
}
public JSType caseNumberType() {
return matchesExpectation("number") ? getNativeType(NUMBER_TYPE) : null;
}
public JSType caseObjectType(ObjectType type) {
if (value.equals("function")) {
JSType ctorType = getNativeType(U2U_CONSTRUCTOR_TYPE);
return resultEqualsValue && ctorType.isSubtype(type) ? ctorType : null;
}
return matchesExpectation("object") ? type : null;
}
public JSType caseStringType() {
return matchesExpectation("string") ? getNativeType(STRING_TYPE) : null;
}
public JSType caseVoidType() {
return matchesExpectation("undefined") ? getNativeType(VOID_TYPE) : null;
}
}
/**
* Returns a version of type where undefined is not present.
*/
final JSType getRestrictedWithoutUndefined(JSType type) {
return type == null ? null : type.visit(restrictUndefinedVisitor);
}
/**
* Returns a version of type where null is not present.
*/
final JSType getRestrictedWithoutNull(JSType type) {
return
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS> != null) {
check(externsRoot, true);
}
check(jsRoot, false);
potentialChecks.flush();
}
/** Main entry point of this phase for testing code. */
public Scope processForTesting(Node externsRoot, Node jsRoot) {
Preconditions.checkState(scopeCreator == null);
Preconditions.checkState(topScope == null);
Preconditions.checkState(jsRoot.getParent() != null);
Node externsAndJsRoot = jsRoot.getParent();
scopeCreator = new MemoizedScopeCreator(new TypedScopeCreator(compiler));
topScope = scopeCreator.createScope(externsAndJsRoot, null);
TypeInferencePass inference = new TypeInferencePass(compiler,
reverseInterpreter, topScope, scopeCreator);
inference.process(externsRoot, jsRoot);
process(externsRoot, jsRoot);
return topScope;
}
public void check(Node node, boolean externs) {
Preconditions.checkNotNull(node);
NodeTraversal t = new NodeTraversal(compiler, this, scopeCreator);
inExterns = externs;
t.traverseWithScope(node, topScope);
if (externs) {
inferJSDocInfo.process(node, null);
} else {
inferJSDocInfo.process(null, node);
}
}
public boolean shouldTraverse(
NodeTraversal t, Node n, Node parent) {
JSDocInfo info;
switch (n.getType()) {
case Token.SCRIPT:
case Token.VAR:
// @notypecheck
info = n.getJSDocInfo();
if (info != null && info.isNoTypeCheck()) {
return false;
}
break;
case Token.FUNCTION:
// @notypecheck
info = n.getJSDocInfo();
info = (info == null) ? parent.getJSDocInfo() : info;
if (info != null && info.isNoTypeCheck()) {
return false;
}
// normal type checking
final TypeCheck outerThis = this;
final Scope outerScope = t.getScope();
final FunctionType functionType = (FunctionType) n.getJSType();
final String functionPrivateName = n.getFirstChild().getString();
if (functionPrivateName != null
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS> break;
case Token.REF_SPECIAL:
ensureTyped(t, n);
break;
case Token.GET_REF:
ensureTyped(t, n, getJSType(n.getFirstChild()));
break;
case Token.NULL:
ensureTyped(t, n, NULL_TYPE);
break;
case Token.NUMBER:
if (n.getParent().getType() != Token.OBJECTLIT) {
ensureTyped(t, n, NUMBER_TYPE);
} else {
typeable = false;
}
break;
case Token.ARRAYLIT:
ensureTyped(t, n, ARRAY_TYPE);
break;
case Token.STRING:
if (n.getParent().getType() != Token.OBJECTLIT) {
ensureTyped(t, n, STRING_TYPE);
} else {
typeable = false;
}
break;
case Token.REGEXP:
ensureTyped(t, n, REGEXP_TYPE);
break;
case Token.GETPROP:
visitGetProp(t, n, parent);
typeable = !(parent.getType() == Token.ASSIGN &&
parent.getFirstChild() == n);
break;
case Token.GETELEM:
visitGetElem(t, n);
// The type of GETELEM is always unknown, so no point counting that.
// If that unknown leaks elsewhere (say by an assignment to another
// variable), then it will be counted.
typeable = false;
break;
case Token.VAR:
visitVar(t, n);
typeable = false;
break;
case Token.NEW:
visitNew(t, n);
typeable = true;
break;
case Token.CALL:
visitCall(t, n);
typeable = !NodeUtil.isExpressionNode(parent);
break;
case Token.RETURN:
visitReturn(t, n);
typeable = false;
break;
case Token.DEC:
case Token.INC:
left = n.getFirstChild();
validator.expectNumber(
t, left, getJSType(left), "increment/decrement");
ensureTyped(t, n, NUMBER_TYPE);
break;
case Token.NOT:
ensureTyped(t, n, BOOLEAN_TYPE);
break;
case Token.VOID:
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS> ensureTyped(t, n, VOID_TYPE);
break;
case Token.TYPEOF:
ensureTyped(t, n, STRING_TYPE);
break;
case Token.BITNOT:
childType = getJSType(n.getFirstChild());
if (!childType.matchesInt32Context()) {
t.report(n, BIT_OPERATION, NodeUtil.opToStr(n.getType()),
childType.toString());
}
ensureTyped(t, n, NUMBER_TYPE);
break;
case Token.POS:
case Token.NEG:
left = n.getFirstChild();
validator.expectNumber(t, left, getJSType(left), "sign operator");
ensureTyped(t, n, NUMBER_TYPE);
break;
case Token.EQ:
case Token.NE: {
leftType = getJSType(n.getFirstChild());
rightType = getJSType(n.getLastChild());
JSType leftTypeRestricted = leftType.restrictByNotNullOrUndefined();
JSType rightTypeRestricted = rightType.restrictByNotNullOrUndefined();
TernaryValue result =
leftTypeRestricted.testForEquality(rightTypeRestricted);
if (result != TernaryValue.UNKNOWN) {
if (n.getType() == Token.NE) {
result = result.not();
}
t.report(n, DETERMINISTIC_TEST, leftType.toString(),
rightType.toString(), result.toString());
}
ensureTyped(t, n, BOOLEAN_TYPE);
break;
}
case Token.SHEQ:
case Token.SHNE: {
leftType = getJSType(n.getFirstChild());
rightType = getJSType(n.getLastChild());
JSType leftTypeRestricted = leftType.restrictByNotNullOrUndefined();
JSType rightTypeRestricted = rightType.restrictByNotNullOrUndefined();
if (!leftTypeRestricted.canTestForShallowEqualityWith(
rightTypeRestricted)) {
t.report(n, DETERMINISTIC_TEST_NO_RESULT, leftType.toString(),
rightType.toString());
}
ensureTyped(t, n, BOOLEAN_TYPE);
break;
}
case Token.LT:
case Token.LE:
case Token.GT:
case Token.GE:
left
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>Resolved()) {
return namedType.getReferenceName();
}
} else if (type.isUnionType()) {
for (JSType alt : ((UnionType) type).getAlternates()) {
if (alt.isUnknownType()) {
String unresolvedReference = getUnresolvedReference(alt);
if (unresolvedReference != null) {
return unresolvedReference;
}
}
}
}
return null;
}
/**
* Visits an assignment <code>lvalue = rvalue</code>. If the
* <code>lvalue</code> is a prototype modification, we change the schema
* of the object type it is referring to.
* @param t the traversal
* @param assign the assign node
* (<code>assign.getType() == Token.ASSIGN</code> is an implicit invariant)
*/
private void visitAssign(NodeTraversal t, Node assign) {
JSDocInfo info = assign.getJSDocInfo();
Node lvalue = assign.getFirstChild();
Node rvalue = assign.getLastChild();
if (lvalue.getType() == Token.GETPROP) {
Node object = lvalue.getFirstChild();
JSType objectJsType = getJSType(object);
String property = lvalue.getLastChild().getString();
// the first name in this getprop refers to an interface
// we perform checks in addition to the ones below
if (object.getType() == Token.GETPROP) {
JSType jsType = getJSType(object.getFirstChild());
if (jsType.isInterface() &&
object.getLastChild().getString().equals("prototype")) {
visitInterfaceGetprop(t, assign, object, property, lvalue, rvalue);
}
}
// /** @type ... */object.name = ...;
if (info != null && info.hasType()) {
visitAnnotatedAssignGetprop(t, assign,
info.getType().evaluate(t.getScope()), object,
property, rvalue);
return;
}
// /** @enum ... */object.name = ...;
if (info != null && info.hasEnumParameterType()) {
checkEnumInitializer(
t, rvalue, info.getEnumParameterType().evaluate(t.getScope()));
return;
}
// object.prototype = ...
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>;
if (property.equals("prototype")) {
if (objectJsType instanceof FunctionType) {
FunctionType functionType = (FunctionType) objectJsType;
if (functionType.isConstructor()) {
JSType rvalueType = rvalue.getJSType();
validator.expectObject(t, rvalue, rvalueType,
OVERRIDING_PROTOTYPE_WITH_NON_OBJECT);
}
} else {
// TODO(user): might want to flag that
}
return;
}
// object.prototype.property = ...;
if (object.getType() == Token.GETPROP) {
Node object2 = object.getFirstChild();
String property2 = NodeUtil.getStringValue(object.getLastChild());
if ("prototype".equals(property2)) {
JSType jsType = object2.getJSType();
if (jsType instanceof FunctionType) {
FunctionType functionType = (FunctionType) jsType;
if (functionType.isConstructor() || functionType.isInterface()) {
checkDeclaredPropertyInheritance(
t, assign, functionType, property, info, getJSType(rvalue));
}
} else {
// TODO(user): might want to flag that
}
return;
}
}
// object.property = ...;
ObjectType type = ObjectType.cast(
objectJsType.restrictByNotNullOrUndefined());
if (type != null) {
if (type.hasProperty(property) &&
!type.isPropertyTypeInferred(property) &&
!propertyIsImplicitCast(type, property)) {
validator.expectCanAssignToPropertyOf(
t, assign, getJSType(rvalue),
type.getPropertyType(property), object, property);
}
return;
}
} else if (lvalue.getType() == Token.NAME) {
// variable with inferred type case
JSType rvalueType = getJSType(assign.getLastChild());
Var var = t.getScope().getVar(lvalue.getString());
if (var != null) {
if (var.isTypeInferred()) {
return;
}
}
}
// fall through case
JSType leftType = getJSType(lvalue);
Node rightChild = assign.getLastChild();
JSType rightType = getJSType(rightChild);
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>,
propertyName, ctorType.getInstanceType().toString()));
}
}
/**
* Visits an ASSIGN node for cases such as
* <pre>
* interface.property2.property = ...;
* </pre>
*/
private void visitInterfaceGetprop(NodeTraversal t, Node assign, Node object,
String property, Node lvalue, Node rvalue) {
JSType rvalueType = getJSType(rvalue);
String abstractMethodName =
compiler.getCodingConvention().getAbstractMethodName();
if (!rvalueType.isOrdinaryFunction() &&
!(rvalue.isQualifiedName() &&
rvalue.getQualifiedName().equals(abstractMethodName))) {
compiler.report(JSError.make(t, object, INTERFACE_FUNCTION_MEMBERS_ONLY,
abstractMethodName));
}
if (assign.getLastChild().getType() == Token.FUNCTION
&& !NodeUtil.isEmptyBlock(assign.getLastChild().getLastChild())) {
compiler.report(JSError.make(t, object, INTERFACE_FUNCTION_NOT_EMPTY,
abstractMethodName));
}
}
/**
* Visits an ASSIGN node for cases such as
* <pre>
* object.property = ...;
* </pre>
* that have an {@code @type} annotation.
*/
private void visitAnnotatedAssignGetprop(NodeTraversal t,
Node assign, JSType type, Node object, String property, Node rvalue) {
// verifying that the rvalue has the correct type
validator.expectCanAssignToPropertyOf(t, assign, getJSType(rvalue), type,
object, property);
}
/**
* Visits a NAME node.
*
* @param t The node traversal object that supplies context, such as the
* scope chain to use in name lookups as well as error reporting.
* @param n The node being visited.
* @param parent The parent of the node n.
* @return whether the node is typeable or not
*/
boolean visitName(NodeTraversal t, Node n, Node parent) {
// At this stage, we need to determine whether this is a leaf
// node in an expression (which therefore needs to have a type
// assigned for it) versus some other decorative node that we
// can safely ignore.
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>
return;
}
checkPropertyAccess(childType, property.getString(), t, n);
ensureTyped(t, n);
}
/**
* Make sure that the access of this property is ok.
*/
private void checkPropertyAccess(JSType childType, String propName,
NodeTraversal t, Node n) {
ObjectType objectType = childType.dereference();
if (objectType != null) {
JSType propType = getJSType(n);
if ((!objectType.hasProperty(propName) ||
objectType.equals(typeRegistry.getNativeType(UNKNOWN_TYPE))) &&
propType.equals(typeRegistry.getNativeType(UNKNOWN_TYPE))) {
if (objectType instanceof EnumType) {
t.report(n, INEXISTENT_ENUM_ELEMENT, propName);
} else if (!objectType.isEmptyType() &&
reportMissingProperties && !isPropertyTest(n)) {
if (!typeRegistry.canPropertyBeDefined(objectType, propName)) {
t.report(n, INEXISTENT_PROPERTY, propName,
validator.getReadableJSTypeName(n.getFirstChild(), true));
}
}
}
} else {
// TODO(nicksantos): might want to flag the access on a non object when
// it's impossible to get a property from this type.
}
}
/**
* Determines whether this node is testing for the existence of a property.
* If true, we will not emit warnings about a missing property.
*
* @param getProp The GETPROP being tested.
*/
private boolean isPropertyTest(Node getProp) {
Node parent = getProp.getParent();
switch (parent.getType()) {
case Token.CALL:
return parent.getFirstChild() != getProp &&
compiler.getCodingConvention().isPropertyTestFunction(parent);
case Token.IF:
case Token.WHILE:
case Token.DO:
case Token.FOR:
return NodeUtil.getConditionExpression(parent) == getProp;
case Token.INSTANCEOF:
case Token.TYPEOF:
return true;
case Token.AND:
case Token.HOOK:
return parent.getFirstChild() == getProp;
}
return false;
}
/**
* Visits a GET
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS> != null) {
FunctionType interfaceConstructor =
baseInterfaceObj.getConstructor();
if (interfaceConstructor != null &&
!interfaceConstructor.isInterface()) {
badImplementedType = true;
}
} else {
badImplementedType = true;
}
if (badImplementedType) {
t.report(n, BAD_IMPLEMENTED_TYPE, functionPrivateName);
}
}
if (functionType.isConstructor()) {
validator.expectAllInterfacePropertiesImplemented(functionType);
}
}
}
/**
* Visits a CALL node.
*
* @param t The node traversal object that supplies context, such as the
* scope chain to use in name lookups as well as error reporting.
* @param n The node being visited.
*/
private void visitCall(NodeTraversal t, Node n) {
Node child = n.getFirstChild();
JSType childType = getJSType(child).restrictByNotNullOrUndefined();
if (!childType.canBeCalled()) {
t.report(n, NOT_CALLABLE, childType.toString());
ensureTyped(t, n);
return;
}
// A couple of types can be called as if they were functions.
// If it is a function type, then validate parameters.
if (childType instanceof FunctionType) {
FunctionType functionType = (FunctionType) childType;
// Non-native constructors should never be called directly.
if (functionType.isConstructor() &&
!functionType.isNativeObjectType()) {
t.report(n, CONSTRUCTOR_NOT_CALLABLE, childType.toString());
}
visitParameterList(t, n, functionType);
ensureTyped(t, n, functionType.getReturnType());
} else {
ensureTyped(t, n);
}
// TODO: Add something to check for calls of RegExp objects, which is not
// supported by IE. Either say something about the return type or warn
// about the non-portability of the call or both.
}
/**
* Visits the parameters of a CALL or a NEW node.
*/
private void visitParameterList(NodeTraversal t, Node call,
FunctionType functionType) {
Iterator<Node> arguments = call.children().iterator();
arguments.next(); // skip the function name
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS> Iterator<Node> parameters = functionType.getParameters().iterator();
int ordinal = 0;
while (arguments.hasNext() && parameters.hasNext()) {
Node parameter = parameters.next();
Node argument = arguments.next();
ordinal++;
validator.expectArgumentMatchesParameter(t, argument,
getJSType(argument), getJSType(parameter), call, ordinal);
}
int numArgs = call.getChildCount() - 1;
int minArgs = functionType.getMinArguments();
int maxArgs = functionType.getMaxArguments();
if (minArgs > numArgs || maxArgs < numArgs) {
t.getCompiler().report(
JSError.make(t, call, WRONG_ARGUMENT_COUNT,
validator.getReadableJSTypeName(call.getFirstChild(), false),
String.valueOf(numArgs), String.valueOf(minArgs),
maxArgs != Integer.MAX_VALUE ?
" and no more than " + maxArgs + " argument(s)" : ""));
}
}
/**
* Visits a RETURN node.
*
* @param t The node traversal object that supplies context, such as the
* scope chain to use in name lookups as well as error reporting.
* @param n The node being visited.
*/
private void visitReturn(NodeTraversal t, Node n) {
Node function = t.getEnclosingFunction();
// This is a misplaced return, but the real JS will fail to compile,
// so let it go.
if (function == null) {
return;
}
JSType jsType = getJSType(function);
if (jsType instanceof FunctionType) {
FunctionType functionType = (FunctionType) jsType;
JSType returnType = functionType.getReturnType();
// if no return type is specified, undefined must be returned
// (it's a void function)
if (returnType == null) {
returnType = getNativeType(VOID_TYPE);
}
// fetching the returned value's type
Node valueNode = n.getFirstChild();
JSType actualReturnType;
if (valueNode == null) {
actualReturnType = getNativeType(VOID_TYPE);
valueNode = n;
} else {
actualReturnType = getJSType(valueNode);
}
// verifying
validator.expectCanAssignTo
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>(t, valueNode, actualReturnType, returnType,
"inconsistent return type");
}
}
/**
* This function unifies the type checking involved in the core binary
* operators and the corresponding assignment operators. The representation
* used internally is such that common code can handle both kinds of
* operators easily.
*
* @param op The operator.
* @param t The traversal object, needed to report errors.
* @param n The node being checked.
*/
private void visitBinaryOperator(int op, NodeTraversal t, Node n) {
Node left = n.getFirstChild();
JSType leftType = getJSType(left);
Node right = n.getLastChild();
JSType rightType = getJSType(right);
switch (op) {
case Token.ASSIGN_LSH:
case Token.ASSIGN_RSH:
case Token.LSH:
case Token.RSH:
case Token.ASSIGN_URSH:
case Token.URSH:
if (!leftType.matchesInt32Context()) {
t.report(left, BIT_OPERATION,
NodeUtil.opToStr(n.getType()), leftType.toString());
}
if (!rightType.matchesUint32Context()) {
t.report(right, BIT_OPERATION,
NodeUtil.opToStr(n.getType()), rightType.toString());
}
break;
case Token.ASSIGN_DIV:
case Token.ASSIGN_MOD:
case Token.ASSIGN_MUL:
case Token.ASSIGN_SUB:
case Token.DIV:
case Token.MOD:
case Token.MUL:
case Token.SUB:
validator.expectNumber(t, left, leftType, "left operand");
validator.expectNumber(t, right, rightType, "right operand");
break;
case Token.ASSIGN_BITAND:
case Token.ASSIGN_BITXOR:
case Token.ASSIGN_BITOR:
case Token.BITAND:
case Token.BITXOR:
case Token.BITOR:
validator.expectBitwiseable(t, left, leftType,
"bad left operand to bitwise operator");
validator.expectBitwiseable(t, right, rightType,
"bad right operand to bitwise operator");
break;
case Token.ASSIGN_ADD
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>/*
* Copyright 2009 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
/**
* A factory for creating JSCompiler passes based on the Options
* injected. Contains all meta-data about compiler passes (like
* whether it can be run multiple times, a human-readable name for
* logging, etc.).
*
* @author nicksantos@google.com (Nick Santos)
*/
public abstract class PassFactory {
private final String name;
private final boolean isOneTimePass;
private boolean isCreated = false;
/**
* @param name The name of the pass that this factory creates.
* @param isOneTimePass If true, the pass produced by this factory can
* only be run once.
*/
protected PassFactory(String name, boolean isOneTimePass) {
this.name = name;
this.isOneTimePass = isOneTimePass;
}
/**
* @return The name of this pass.
*/
String getName() {
return name;
}
/**
* @return Whether the pass produced by this factory can only be run once.
*/
boolean isOneTimePass() {
return isOneTimePass;
}
/**
* Make a new pass factory that only creates one-time passes.
*/
PassFactory makeOneTimePass() {
if (isOneTimePass()) {
return this;
}
final PassFactory self = this;
return new PassFactory(name, true /* one time pass */) {
@Override
protected CompilerPass createInternal(AbstractCompiler compiler) {
return self.createInternal(compiler);
}
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>/*
* Copyright 2009 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
/**
* Provides common data structures for program analysis.
*
* Clients of the symbol table are strictly responsible for keeping
* the data structures up to date. The testing infrastructure is
* responsible for verifying that they do this.
*
* If a pass does not want to keep its data structures up to date,
* then it should not use the symbol table--it should directly invoke
* the factory for the data structure it wants.
*
* @author nicksantos@google.com (Nick Santos)
*/
class SymbolTable implements ScopeCreator, CodeChangeHandler {
static final DiagnosticType MISSING_VARIABLE =
DiagnosticType.error(
"JSC_MISSING_VARIABLE",
"Missing variable name: {0}");
static final DiagnosticType MOVED_VARIABLE =
DiagnosticType.error(
"JSC_MOVED_VARIABLE",
"Moved variable name: {0}");
static final DiagnosticType VARIABLE_COUNT_MISMATCH =
DiagnosticType.error(
"JSC_VARIABLE_COUNT_MISMATCH",
"Variable count does not match."
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS> data structures cached by this table.
*/
private static class MemoizedData {
private Map<Node, Scope> scopes = Maps.newHashMap();
}
//----------------------------------------------------------------------------
// Verification of consistency. Only for tests.
/**
* Check that this symbol table has been kept up to date. Compiler warnings
* will be emitted if anything is wrong.
* @param expectedRoot The root of the expected AST.
* @param actualRoot The root of the actual AST used with this symbol table.
*/
void verify(Node expectedRoot, Node actualRoot) {
VerifyingCallback callback = new VerifyingCallback(
expectedRoot, actualRoot);
callback.verify();
}
/**
* A callback that traverses an AST root and builds all the
* secondary data structures for it.
*/
private class VerifyingCallback implements ScopedCallback {
private final List<Scope> expectedScopes = Lists.newArrayList();
private final List<Scope> actualScopes = Lists.newArrayList();
private boolean collectingExpected = true;
private final Node actualRoot;
private final Node expectedRoot;
private VerifyingCallback(Node expectedRoot, Node actualRoot) {
this.actualRoot = actualRoot;
this.expectedRoot = expectedRoot;
}
@Override
public boolean shouldTraverse(
NodeTraversal nodeTraversal, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node n, Node parent) {}
@Override
public void enterScope(NodeTraversal t) {}
@Override
public void exitScope(NodeTraversal t) {
if (collectingExpected) {
expectedScopes.add(t.getScope());
} else {
actualScopes.add(t.getScope());
}
}
private void verify() {
if (cache == null) {
// The symbol table was never used, so no need to check anything.
return;
}
if (!cache.scopes.isEmpty()) {
verifyScopes();
}
}
private void verifyScopes() {
collectingExpected = true;
NodeTraversal.traverse(compiler, expectedRoot, this);
collectingExpected = false;
(new NodeTraversal(compiler, this, SymbolTable.this))
.traverse(actualRoot);
// This must be true unless something went horribly, horribly wrong.
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>
Preconditions.checkState(expectedScopes.size() == actualScopes.size());
for (int i = 0; i < expectedScopes.size(); i++) {
Scope expectedScope = expectedScopes.get(i);
Scope actualScope = actualScopes.get(i);
if (!checkNodesMatch(expectedScope.getRootNode(),
actualScope.getRootNode())) {
compiler.report(
JSError.make(
SCOPE_MISMATCH,
expectedScope.getRootNode().toStringTree(),
actualScope.getRootNode().toStringTree()));
continue;
}
if (expectedScope.getVarCount() != actualScope.getVarCount()) {
compiler.report(
JSError.make(
VARIABLE_COUNT_MISMATCH,
Integer.toString(expectedScope.getVarCount()),
Integer.toString(actualScope.getVarCount())));
} else {
Iterator<Var> it = expectedScope.getVars();
while (it.hasNext()) {
Var var = it.next();
Scope.Var actualVar = actualScope.getVar(var.getName());
if (actualVar == null ||
expectedScope.getVar(var.getName()) != var) {
compiler.report(
JSError.make(MISSING_VARIABLE, var.getName()));
} else if (
!checkNodesMatch(
var.getNameNode(),
actualVar.getNameNode()) ||
!isNodeAttached(actualVar.getNameNode())) {
compiler.report(
JSError.make(MOVED_VARIABLE, var.getName()));
}
}
}
}
}
/**
* Check that the two nodes have the same relative position in the tree.
*/
private boolean checkNodesMatch(Node nodeA, Node nodeB) {
Node currentA = nodeA;
Node currentB = nodeB;
while (currentA != null && currentB != null) {
if (currentA.getType() != currentB.getType() ||
!currentA.isEquivalentTo(currentB)) {
return false;
}
currentA = currentA.getParent();
currentB = currentB.getParent();
}
return currentA == null && currentB == null;
}
private boolean isNodeAttached(Node node) {
// Make sure the cached var is still attached.
for (Node current = node;
current != null; current
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS> = current.getParent()) {
if (current.getType() == Token.SCRIPT) {
return true;
}
}
return false;
}
}
}
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>.mozilla.rhino.ast.SwitchStatement;
import com.google.javascript.jscomp.mozilla.rhino.ast.ThrowStatement;
import com.google.javascript.jscomp.mozilla.rhino.ast.TryStatement;
import com.google.javascript.jscomp.mozilla.rhino.ast.UnaryExpression;
import com.google.javascript.jscomp.mozilla.rhino.ast.VariableDeclaration;
import com.google.javascript.jscomp.mozilla.rhino.ast.VariableInitializer;
import com.google.javascript.jscomp.mozilla.rhino.ast.WhileLoop;
import com.google.javascript.jscomp.mozilla.rhino.ast.WithStatement;
import com.google.javascript.rhino.JSDocInfo;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.ScriptOrFnNode;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.jstype.JSTypeRegistry;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
/**
* IRFactory transforms the new AST to the old AST.
*
*
*/
public class IRFactory {
private final String sourceString;
private final String sourceName;
private final Config config;
private final JSTypeRegistry registry;
private final ErrorReporter errorReporter;
private final TransformDispatcher transformDispatcher;
// non-static for thread safety
private final Set<String> ALLOWED_DIRECTIVES = Sets.newHashSet("use strict");
// Nodes with JSDoc comments, indexed by the text of the JSDoc comment.
//
// It's likely that two or more nodes in the same file may have the same
// jsdoc comment. In general, that's ok.
//
// There's one edge case where this might cause problems. If two JSDoc
// comments have the same text, and the first JSDoc comment is not attached
// to a node, then the second node will get the first JSDoc comment
// instead of the second. When this happens, it probably won't cause any
// problems. The two JSDoc comments will be exactly the same,
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>
* @param comment The JsDoc comment to parse.
* @param lineno The line number of the node this comment is attached to.
* @param fileLevelJsDocBuilder The builder for file-level JSDocInfo.
* @param fileOverviewInfo The current @fileoverview JSDocInfo, so that the
* parser may warn if another @fileoverview is found. May be null.
* @return A JSDocInfoParser. Will contain either fileoverview jsdoc, or
* normal jsdoc, or no jsdoc (if the method parses to the wrong level).
*/
private JsDocInfoParser createJsDocInfoParser(
String comment, int lineno, int position,
Node.FileLevelJsDocBuilder fileLevelJsDocBuilder,
JSDocInfo fileOverviewInfo) {
// The JsDocInfoParser expects the comment without the initial '/**'.
int numOpeningChars = 3;
JsDocInfoParser jsdocParser =
new JsDocInfoParser(
new JsDocTokenStream(comment.substring(numOpeningChars),
lineno,
position2charno(position) + numOpeningChars),
sourceName,
config,
errorReporter);
jsdocParser.setFileLevelJsDocBuilder(fileLevelJsDocBuilder);
jsdocParser.setFileOverviewJSDocInfo(fileOverviewInfo);
jsdocParser.parse();
return jsdocParser;
}
/** Attach JSDocInfo to a node, if we can find one. */
private void attachJsDoc(Comment comment, JSDocInfo info) {
Collection<NodeWithJsDoc> candidates =
nodesWithJsDoc.get(comment.getValue());
if (candidates.isEmpty()) {
return;
}
Iterator<NodeWithJsDoc> candidateIter = candidates.iterator();
Node node = candidateIter.next().node;
candidateIter.remove();
node.setJSDocInfo(info);
if (info.hasEnumParameterType()) {
if (node.getType() == Token.NAME) {
registry.identifyEnumName(node.getString());
} else if (node.getType() == Token.VAR &&
node.getChildCount() == 1) {
registry.identifyEnumName(
node.getFirstChild().getString());
} else if (node.getType() == Token.ASSIGN
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>
node.addChildToBack(c);
}
if (skipCount > 0) {
int[] skipIndexes = new int[skipCount];
int i = 0;
int j = 0;
for (Node child : node.children()) {
if (child.getType() == Token.EMPTY) {
node.removeChild(child);
skipIndexes[j] = i;
j++;
}
i++;
}
node.putProp(Node.SKIP_INDEXES_PROP, skipIndexes);
}
return node;
}
@Override
Node processAssignment(Assignment assignmentNode) {
return processInfixExpression(assignmentNode);
}
@Override
Node processAstRoot(AstRoot rootNode) {
Node node = new ScriptOrFnNode(Token.SCRIPT);
for (com.google.javascript.jscomp.mozilla.rhino.Node child : rootNode) {
node.addChildToBack(transform((AstNode)child));
}
parseDirectives(node);
return node;
}
/**
* Parse the directives, encode them in the AST, and remove their nodes.
*
* For information on ES5 directives, see section 14.1 of
* Ecma-262, Edition 5.
*
* It would be nice if Rhino would eventually take care of this for
* us, but right now their directive-processing is a one-off.
*/
private void parseDirectives(Node node) {
// Remove all the directives, and encode them in the AST.
Set<String> directives = null;
while (isDirective(node.getFirstChild())) {
String directive = node.removeFirstChild().getFirstChild().getString();
if (directives == null) {
directives = Sets.newHashSet(directive);
} else {
directives.add(directive);
}
}
if (directives != null) {
node.setDirectives(directives);
}
}
private boolean isDirective(Node n) {
if (n == null) return false;
int nType = n.getType();
return (nType == Token.EXPR_RESULT || nType == Token.EXPR_VOID) &&
n.getFirstChild().getType() == Token.STRING &&
ALLOWED_DIRECTIVES.contains(n.getFirstChild
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>
// Position in new ASTNode is to start of expression, but old-fashioned
// line numbers from Node reference the operator token. Add the offset
// to the operator to get the correct character number.
n.setCharno(position2charno(exprNode.getAbsolutePosition() +
exprNode.getOperatorPosition()));
return n;
}
@Override
Node processKeywordLiteral(KeywordLiteral literalNode) {
return new Node(transformTokenType(literalNode.getType()));
}
@Override
Node processLabel(Label labelNode) {
return Node.newString(Token.NAME, labelNode.getName());
}
@Override
Node processLabeledStatement(LabeledStatement statementNode) {
Node node = new Node(Token.LABEL);
Node prev = null;
Node cur = node;
for (Label label : statementNode.getLabels()) {
if (prev != null) {
prev.addChildToBack(cur);
}
cur.addChildToBack(transform(label));
prev = cur;
cur = new Node(Token.LABEL);
}
prev.addChildToBack(transform(statementNode.getStatement()));
return node;
}
@Override
Node processName(Name nameNode) {
return Node.newString(Token.NAME, nameNode.getIdentifier());
}
@Override
Node processNewExpression(NewExpression exprNode) {
return processFunctionCall(exprNode);
}
@Override
Node processNumberLiteral(NumberLiteral literalNode) {
Node newNode = Node.newNumber(literalNode.getNumber());
return newNode;
}
@Override
Node processObjectLiteral(ObjectLiteral literalNode) {
if (literalNode.isDestructuring()) {
reportDestructuringAssign(literalNode);
}
Node node = new Node(Token.OBJECTLIT);
for (ObjectProperty el : literalNode.getElements()) {
node.addChildToBack(transformAsString(el.getLeft()));
node.addChildToBack(transform(el.getRight()));
}
return node;
}
@Override
Node processObjectProperty(ObjectProperty propertyNode) {
return processInfixExpression(propertyNode);
}
@Override
Node processParenthesizedExpression(ParenthesizedExpression exprNode) {
Node node = transform(exprNode.getExpression());
node
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>.append(':');
b.append(error.lineNumber);
}
b.append(": ");
}
b.append(getLevelName(warning ? CheckLevel.WARNING : CheckLevel.ERROR));
b.append(" - ");
b.append(error.description);
b.append('\n');
if (sourceExcerpt != null) {
b.append(sourceExcerpt);
b.append('\n');
int charno = error.getCharno();
// padding equal to the excerpt and arrow at the end
if (excerpt.equals(LINE)
&& 0 <= charno && charno < sourceExcerpt.length()) {
for (int i = 0; i < charno; i++) {
char c = sourceExcerpt.charAt(i);
if (Character.isWhitespace(c)) {
b.append(c);
} else {
b.append(' ');
}
}
b.append("^\n");
}
}
return b.toString();
}
/**
* Formats a region by appending line numbers in front, e.g.
* <pre> 9| if (foo) {
* 10| alert('bar');
* 11| }</pre>
* and return line excerpt without any modification.
*/
static class LineNumberingFormatter implements ExcerptFormatter {
public String formatLine(String line, int lineNumber) {
return line;
}
public String formatRegion(Region region) {
if (region == null) {
return null;
}
String code = region.getSourceExcerpt();
if (code.length() == 0) {
return null;
}
// max length of the number display
int numberLength = Integer.toString(region.getEndingLineNumber())
.length();
// formatting
StringBuilder builder = new StringBuilder(code.length() * 2);
int start = 0;
int end = code.indexOf('\n', start);
int lineNumber = region.getBeginningLineNumber();
while (start >= 0) {
// line extraction
String line;
if (end < 0) {
line = code.substring(start);
if (line.length() == 0) {
return builder.substring(0, builder.length() -
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS> /**
* Gets the number of properties of this object.
*/
@Override
public int getPropertiesCount() {
ObjectType implicitPrototype = getImplicitPrototype();
if (implicitPrototype == null) {
return this.properties.size();
}
int localCount = 0;
for (String property : properties.keySet()) {
if (!implicitPrototype.hasProperty(property)) {
localCount++;
}
}
return implicitPrototype.getPropertiesCount() + localCount;
}
@Override
public boolean hasProperty(String propertyName) {
if (properties.get(propertyName) != null) {
return true;
}
ObjectType implicitPrototype = getImplicitPrototype();
if (implicitPrototype != null) {
return implicitPrototype.hasProperty(propertyName);
}
return false;
}
@Override
public boolean hasOwnProperty(String propertyName) {
return properties.get(propertyName) != null;
}
@Override
public Set<String> getOwnPropertyNames() {
return properties.keySet();
}
@Override
public boolean isPropertyTypeDeclared(String property) {
Property p = properties.get(property);
if (p == null) {
ObjectType implicitPrototype = getImplicitPrototype();
if (implicitPrototype != null) {
return implicitPrototype.isPropertyTypeDeclared(property);
}
// property does not exist
return false;
}
return !p.inferred;
}
@Override
protected void collectPropertyNames(Set<String> props) {
for (String prop : properties.keySet()) {
props.add(prop);
}
ObjectType implicitPrototype = getImplicitPrototype();
if (implicitPrototype != null) {
implicitPrototype.collectPropertyNames(props);
}
}
@Override
public boolean isPropertyTypeInferred(String property) {
Property p = properties.get(property);
if (p == null) {
ObjectType implicitPrototype = getImplicitPrototype();
if (implicitPrototype != null) {
return implicitPrototype.isPropertyTypeInferred(property);
}
// property does not exist
return false;
}
return p.inferred;
}
@Override
public JSType getPropertyType(String propertyName) {
Property p = properties.get(propertyName);
if (p != null) {
return p.type;
}
ObjectType implicitPrototype = getImplicit
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>link CompilerOptions}.
*/
private MessageFormatter createMessageFormatter() {
boolean colorize = options_.shouldColorizeErrorOutput();
return options_.errorFormat.toFormatter(this, colorize);
}
/**
* Initializes the instance state needed for a compile job.
*/
public void init(JSSourceFile[] externs, JSSourceFile[] inputs,
CompilerOptions options) {
externs_ = makeCompilerInput(externs, true);
modules_ = null;
moduleGraph_ = null;
inputs_ = makeCompilerInput(inputs, false);
options_ = options;
initBasedOnOptions();
initInputsByNameMap();
}
static final DiagnosticType MODULE_DEPENDENCY_ERROR =
DiagnosticType.error("JSC_MODULE_DEPENDENCY_ERROR",
"Bad dependency: {0} -> {1}. "
+ "Modules must be listed in dependency order.");
/**
* Initializes the instance state needed for a compile job.
*/
public void init(JSSourceFile[] externs, JSModule[] modules,
CompilerOptions options) {
checkFirstModule(modules);
externs_ = makeCompilerInput(externs, true);
modules_ = modules;
// Generate the module graph, and report any errors in the module
// specification as errors.
try {
moduleGraph_ = new JSModuleGraph(modules);
} catch (JSModuleGraph.ModuleDependenceException e) {
// problems with the module format. Report as an error. The
// message gives all details.
report(JSError.make(MODULE_DEPENDENCY_ERROR,
e.getModule().getName(), e.getDependentModule().getName()));
return;
}
inputs_ = getAllInputsFromModules();
options_ = options;
initBasedOnOptions();
initInputsByNameMap();
}
/**
* Do any initialization that is dependent on the compiler options.
*/
private void initBasedOnOptions() {
// Create the source map if necessary.
if (options_.sourceMapOutputPath != null) {
sourceMap_ = new SourceMap();
}
}
private CompilerInput[] makeCompilerInput(
JSSourceFile[] files, boolean isExtern) {
CompilerInput [] inputs = new CompilerInput[files.length];
for (int i = 0;
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS> i < files.length; ++i) {
inputs[i] = new CompilerInput(files[i], isExtern);
}
return inputs;
}
private static final DiagnosticType EMPTY_MODULE_LIST_ERROR =
DiagnosticType.error("JSC_EMPTY_MODULE_LIST_ERROR",
"At least one module must be provided");
private static final DiagnosticType EMPTY_ROOT_MODULE_ERROR =
DiagnosticType.error("JSC_EMPTY_ROOT_MODULE_ERROR",
"Root module '{0}' must contain at least one source code input");
/**
* Verifies that at least one module has been provided and that the first one
* has at least one source code input.
*/
private void checkFirstModule(JSModule[] modules) {
if (modules.length == 0) {
report(JSError.make(EMPTY_MODULE_LIST_ERROR));
} else if (modules[0].getInputs().isEmpty()) {
report(JSError.make(EMPTY_ROOT_MODULE_ERROR,
modules[0].getName()));
}
}
static final DiagnosticType DUPLICATE_INPUT_IN_MODULES =
DiagnosticType.error("JSC_DUPLICATE_INPUT_IN_MODULES_ERROR",
"Two modules cannot contain the same input, but module {0} and {1} "
+ "both include \"{2}\"");
/**
* Rebuilds the internal list of inputs by iterating over all modules.
* This is necessary if inputs have been added to or removed from a module
* after the {@link #init(JSSourceFile[], JSModule[], CompilerOptions)} call.
*/
public void rebuildInputsFromModules() {
inputs_ = getAllInputsFromModules();
initInputsByNameMap();
}
/**
* Builds a single list of all module inputs. Verifies that it contains no
* duplicates.
*/
private CompilerInput[] getAllInputsFromModules() {
List<CompilerInput> inputs = new ArrayList<CompilerInput>();
Map<String, JSModule> inputMap = new HashMap<String, JSModule>();
for (JSModule module : modules_) {
for (CompilerInput input : module.getInputs()) {
String inputName = input.getName();
JSModule firstModule = inputMap.get(inputName);
if (firstModule == null) {
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>
inputs.add(input);
inputMap.put(inputName, module);
} else {
report(JSError.make(DUPLICATE_INPUT_IN_MODULES,
firstModule.getName(), module.getName(), inputName));
}
}
}
if (hasErrors()) {
// There's no reason to bother parsing the code.
return new CompilerInput[0];
}
return inputs.toArray(new CompilerInput[inputs.size()]);
}
static final DiagnosticType DUPLICATE_INPUT =
DiagnosticType.error("JSC_DUPLICATE_INPUT", "Duplicate input: {0}");
static final DiagnosticType DUPLICATE_EXTERN_INPUT =
DiagnosticType.error("JSC_DUPLICATE_EXTERN_INPUT",
"Duplicate extern input: {0}");
/**
* Creates a map to make looking up an input by name fast. Also checks for
* duplicate inputs.
*/
void initInputsByNameMap() {
inputsByName_ = new HashMap<String, CompilerInput>();
for (CompilerInput input : externs_) {
String name = input.getName();
if (!inputsByName_.containsKey(name)) {
inputsByName_.put(name, input);
} else {
report(JSError.make(DUPLICATE_EXTERN_INPUT, name));
}
}
for (CompilerInput input : inputs_) {
String name = input.getName();
if (!inputsByName_.containsKey(name)) {
inputsByName_.put(name, input);
} else {
report(JSError.make(DUPLICATE_INPUT, name));
}
}
}
public Result compile(
JSSourceFile extern, JSSourceFile input, CompilerOptions options) {
return compile(extern, new JSSourceFile[] { input }, options);
}
public Result compile(
JSSourceFile extern, JSSourceFile[] input, CompilerOptions options) {
return compile(new JSSourceFile[] { extern }, input, options);
}
public Result compile(
JSSourceFile extern, JSModule[] modules, CompilerOptions options) {
return compile(new JSSourceFile[] { extern }, modules, options);
}
/**
* Compiles a list of inputs.
*/
public Result compile(JSSourceFile[] externs,
JSSourceFile
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>ternExportsPass(this);
process(pass);
externExports_ = pass.getGeneratedExterns();
endPass();
}
void process(CompilerPass p) {
p.process(externsRoot, jsRoot);
}
private final PassFactory sanityCheck =
new PassFactory("sanityCheck", false) {
@Override
protected CompilerPass createInternal(AbstractCompiler compiler) {
return new SanityCheck(compiler);
}
};
private void maybeSanityCheck() {
if (options_.devMode == DevMode.EVERY_PASS) {
runSanityCheck();
}
}
private void runSanityCheck() {
sanityCheck.create(this).process(externsRoot, jsRoot);
}
/**
* Removes try/catch/finally statements for easier debugging.
*/
void removeTryCatchFinally() {
logger_.info("Remove try/catch/finally");
startPass("removeTryCatchFinally");
RemoveTryCatch r = new RemoveTryCatch(this);
process(r);
endPass();
}
/**
* Strips code for smaller compiled code. This is useful for removing debug
* statements to prevent leaking them publicly.
*/
void stripCode(Set<String> stripTypes, Set<String> stripNameSuffixes,
Set<String> stripTypePrefixes, Set<String> stripNamePrefixes) {
logger_.info("Strip code");
startPass("stripCode");
StripCode r = new StripCode(this, stripTypes, stripNameSuffixes,
stripTypePrefixes, stripNamePrefixes);
process(r);
endPass();
}
/**
* Runs custom passes that are designated to run at a particular time.
*/
private void runCustomPasses(CustomPassExecutionTime executionTime) {
if (options_.customPasses != null) {
Tracer t = newTracer("runCustomPasses");
try {
for (CompilerPass p : options_.customPasses.get(executionTime)) {
process(p);
}
} finally {
stopTracer(t, "runCustomPasses");
}
}
}
private Tracer currentTracer = null;
private String currentPassName = null;
/**
* Marks the beginning of a pass.
*/
void startPass(String pass
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>SourceFile().getName();
Preconditions.checkState(
getInput(sourceName) == null,
"Duplicate input of name " + sourceName);
inputsByName_.put(sourceName, new CompilerInput(ast));
}
@Override
JSModuleGraph getModuleGraph() {
return moduleGraph_;
}
@Override
public JSTypeRegistry getTypeRegistry() {
if (typeRegistry == null) {
typeRegistry = new JSTypeRegistry(oldErrorReporter);
}
return typeRegistry;
}
@Override
ScopeCreator getScopeCreator() {
return getPassConfig().getScopeCreator();
}
@Override
public Scope getTopScope() {
return getPassConfig().getTopScope();
}
@Override
public ReverseAbstractInterpreter getReverseAbstractInterpreter() {
if (abstractInterpreter == null) {
ChainableReverseAbstractInterpreter interpreter =
new SemanticReverseAbstractInterpreter(
getCodingConvention(), getTypeRegistry());
if (options_.closurePass) {
interpreter = new ClosureReverseAbstractInterpreter(
getCodingConvention(), getTypeRegistry())
.append(interpreter).getFirst();
}
abstractInterpreter = interpreter;
}
return abstractInterpreter;
}
@Override
TypeValidator getTypeValidator() {
return typeValidator;
}
//------------------------------------------------------------------------
// Parsing
//------------------------------------------------------------------------
/**
* Parses the externs and main inputs.
*
* @return A synthetic root node whose two children are the externs root
* and the main root
*/
Node parseInputs() {
boolean devMode = options_.devMode != DevMode.OFF;
// If old roots exist (we are parsing a second time), detach each of the
// individual file parse trees.
if (externsRoot != null) {
externsRoot.detachChildren();
}
if (jsRoot != null) {
jsRoot.detachChildren();
}
// Parse main js sources.
jsRoot = new Node(Token.BLOCK);
jsRoot.setIsSyntheticBlock(true);
if (options_.tracer.isOn()) {
tracker = new PerformanceTracker(jsRoot,
options_.tracer == TracerMode.ALL);
addChangeHandler(tracker.getCodeChangeHandler());
}
Tracer tracer = newTracer("parseInputs");
try {
// Parse externs sources.
externsRoot = new Node(Token.
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>BLOCK);
externsRoot.setIsSyntheticBlock(true);
for (CompilerInput input : externs_) {
Node n = input.getAstRoot(this);
if (hasErrors()) {
return null;
}
externsRoot.addChildToBack(n);
}
for (CompilerInput input : inputs_) {
Node n = input.getAstRoot(this);
if (hasErrors()) {
return null;
}
// Inputs can have a null AST during initial parse.
if (n == null) {
continue;
}
if (devMode) {
runSanityCheck();
if (hasErrors()) {
return null;
}
}
if (options_.sourceMapOutputPath != null ||
options_.nameReferenceReportPath != null) {
// Annotate the nodes in the tree with information from the
// input file. This information is used to construct the SourceMap.
SourceInformationAnnotator sia =
new SourceInformationAnnotator(input.getName());
NodeTraversal.traverse(this, n, sia);
}
jsRoot.addChildToBack(n);
}
externAndJsRoot = new Node(Token.BLOCK, externsRoot, jsRoot);
externAndJsRoot.setIsSyntheticBlock(true);
return externAndJsRoot;
} finally {
stopTracer(tracer, "parseInputs");
}
}
public Node parse(JSSourceFile file) {
addToDebugLog("Parsing: " + file.getName());
return new JsAst(file).getAstRoot(this);
}
@Override
Node parseSyntheticCode(String js) {
CompilerInput input = new CompilerInput(
JSSourceFile.fromCode(" [synthetic] ", js));
inputsByName_.put(input.getName(), input);
return input.getAstRoot(this);
}
@Override
Node parseSyntheticCode(String fileName, String js) {
return parse(JSSourceFile.fromCode(fileName, js));
}
Node parseTestCode(String js) {
CompilerInput input = new CompilerInput(
JSSourceFile.fromCode(" [testcode] ", js));
if (inputsByName_ == null) {
inputsByName_ = Maps.newHashMap();
}
inputsByName_.put(input
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>.getName(), input);
return input.getAstRoot(this);
}
@Override
ErrorReporter getDefaultErrorReporter() {
return defaultErrorReporter;
}
//------------------------------------------------------------------------
// Convert back to source code
//------------------------------------------------------------------------
/**
* Converts the main parse tree back to js code.
*/
public String toSource() {
return runInCompilerThread(new Callable<String>() {
public String call() throws Exception {
Tracer tracer = newTracer("toSource");
try {
CodeBuilder cb = new CodeBuilder();
if (jsRoot != null) {
int i = 0;
for (Node scriptNode = jsRoot.getFirstChild();
scriptNode != null;
scriptNode = scriptNode.getNext()) {
toSource(cb, i++, scriptNode);
}
}
return cb.toString();
} finally {
stopTracer(tracer, "toSource");
}
}
});
}
/**
* Converts the parse tree for each input back to js code.
*/
public String[] toSourceArray() {
return runInCompilerThread(new Callable<String[]>() {
public String[] call() throws Exception {
Tracer tracer = newTracer("toSourceArray");
try {
int numInputs = inputs_.length;
String[] sources = new String[numInputs];
CodeBuilder cb = new CodeBuilder();
for (int i = 0; i < numInputs; i++) {
Node scriptNode = inputs_[i].getAstRoot(Compiler.this);
cb.reset();
toSource(cb, i, scriptNode);
sources[i] = cb.toString();
}
return sources;
} finally {
stopTracer(tracer, "toSourceArray");
}
}
});
}
/**
* Converts the parse tree for a module back to js code.
*/
public String toSource(final JSModule module) {
return runInCompilerThread(new Callable<String>() {
public String call() throws Exception {
List<CompilerInput> inputs = module.getInputs();
int numInputs = inputs.size();
if (numInputs == 0) {
return "";
}
CodeBuilder cb = new CodeBuilder();
for (int i = 0; i < numInputs; i++) {
Node scriptNode = inputs
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>.get(i).getAstRoot(Compiler.this);
if (scriptNode == null) {
throw new IllegalArgumentException(
"Bad module: " + module.getName());
}
toSource(cb, i, scriptNode);
}
return cb.toString();
}
});
}
/**
* Converts the parse tree for each input in a module back to js code.
*/
public String[] toSourceArray(final JSModule module) {
return runInCompilerThread(new Callable<String[]>() {
public String[] call() throws Exception {
List<CompilerInput> inputs = module.getInputs();
int numInputs = inputs.size();
if (numInputs == 0) {
return new String[0];
}
String[] sources = new String[numInputs];
CodeBuilder cb = new CodeBuilder();
for (int i = 0; i < numInputs; i++) {
Node scriptNode = inputs.get(i).getAstRoot(Compiler.this);
if (scriptNode == null) {
throw new IllegalArgumentException(
"Bad module input: " + inputs.get(i).getName());
}
cb.reset();
toSource(cb, i, scriptNode);
sources[i] = cb.toString();
}
return sources;
}
});
}
/**
* Writes out js code from a root node. If printing input delimiters, this
* method will attach a comment to the start of the text indicating which
* input the output derived from. If there were any preserve annotations
* within the root's source, they will also be printed in a block comment
* at the beginning of the output.
*/
public void toSource(final CodeBuilder cb,
final int inputSeqNum,
final Node root) {
runInCompilerThread(new Callable<Void>() {
public Void call() throws Exception {
if (options_.printInputDelimiter) {
if ((cb.getLength() > 0) && !cb.endsWith("\n")) {
cb.append("\n"); // Make sure that the label starts on a new line
}
Preconditions.checkState(root.getType() == Token.SCRIPT);
String delimiter = options_.inputDelimiter;
String sourceName = (String)root.getProp(Node.SOURCENAME_PROP);
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS> this;
}
/** Returns all text in the text buffer. */
@Override
public String toString() {
return sb.toString();
}
/** Returns the length of the text buffer. */
public int getLength() {
return sb.length();
}
/** Returns the (zero-based) index of the last line in the text buffer. */
int getLineIndex() {
return lineCount;
}
/** Returns the (zero-based) index of the last column in the text buffer. */
int getColumnIndex() {
int index = sb.lastIndexOf("\n");
return (index >= 0) ? sb.length() - (index + 1) : sb.length();
}
/** Determines whether the text ends with the given suffix. */
boolean endsWith(String suffix) {
return (sb.length() > suffix.length())
&& suffix.equals(sb.substring(sb.length() - suffix.length()));
}
}
//------------------------------------------------------------------------
// Optimizations
//------------------------------------------------------------------------
public void optimize() {
PhaseOptimizer phaseOptimizer = new PhaseOptimizer(this, tracker);
if (options_.devMode == DevMode.EVERY_PASS) {
phaseOptimizer.setSanityCheck(sanityCheck);
}
phaseOptimizer.consume(getPassConfig().getOptimizations());
phaseOptimizer.process(externsRoot, jsRoot);
if (hasErrors()) {
return;
}
}
@Override
void setCssRenamingMap(CssRenamingMap map) {
options_.cssRenamingMap = map;
}
@Override
CssRenamingMap getCssRenamingMap() {
return options_.cssRenamingMap;
}
/**
* Reprocesses the current defines over the AST. This is used by GwtCompiler
* to generate N outputs for different targets from the same (checked) AST.
* For each target, we apply the target-specific defines by calling
* {@code processDefines} and then {@code optimize} to optimize the AST
* specifically for that target.
*/
public void processDefines() {
(new DefaultPassConfig(options_)).processDefines.create(this)
.process(externsRoot, jsRoot);
}
boolean isInliningForbidden() {
return options_.propertyRenaming == PropertyRenamingPolicy
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>.HEURISTIC ||
options_.propertyRenaming ==
PropertyRenamingPolicy.AGGRESSIVE_HEURISTIC;
}
/** Control Flow Analysis. */
ControlFlowGraph<Node> computeCFG() {
logger_.info("Computing Control Flow Graph");
Tracer tracer = newTracer("computeCFG");
ControlFlowAnalysis cfa = new ControlFlowAnalysis(this, true);
process(cfa);
stopTracer(tracer, "computeCFG");
return cfa.getCfg();
}
public void normalize() {
logger_.info("Normalizing");
startPass("normalize");
process(new Normalize(this, false));
setNormalized();
endPass();
}
@Override
void prepareAst(Node root) {
Tracer tracer = newTracer("prepareAst");
CompilerPass pass = new PrepareAst(this);
pass.process(null, root);
stopTracer(tracer, "prepareAst");
}
void recordFunctionInformation() {
logger_.info("Recording function information");
startPass("recordFunctionInformation");
RecordFunctionInformation recordFunctionInfoPass =
new RecordFunctionInformation(
this, getPassConfig().getIntermediateState().functionNames);
process(recordFunctionInfoPass);
functionInformationMap_ = recordFunctionInfoPass.getMap();
endPass();
}
protected final CodeChangeHandler.RecentChange recentChange =
new CodeChangeHandler.RecentChange();
private final List<CodeChangeHandler> codeChangeHandlers =
Lists.<CodeChangeHandler>newArrayList();
@Override
void addChangeHandler(CodeChangeHandler handler) {
codeChangeHandlers.add(handler);
}
@Override
void removeChangeHandler(CodeChangeHandler handler) {
codeChangeHandlers.remove(handler);
}
/**
* All passes should call reportCodeChange() when they alter
* the JS tree structure. This is verified by CompilerTestCase.
* This allows us to optimize to a fixed point.
*/
@Override
public void reportCodeChange() {
for (CodeChangeHandler handler : codeChangeHandlers) {
handler.reportChange();
}
}
@Override
public CodingConvention getCodingConvention() {
CodingConvention convention = options_.getCodingConvention();
convention = convention != null ? convention : defaultCodingConvention;
return convention;
}
@Override
public boolean isIdeMode()
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>(str);
debugLog_.append('\n');
logger_.fine(str);
}
private SourceFile getSourceFileByName(String sourceName) {
if (inputsByName_.containsKey(sourceName)) {
return inputsByName_.get(sourceName).getSourceFile();
}
return null;
}
public String getSourceLine(String sourceName, int lineNumber) {
if (lineNumber < 1) {
return null;
}
SourceFile input = getSourceFileByName(sourceName);
if (input != null) {
return input.getLine(lineNumber);
}
return null;
}
public Region getSourceRegion(String sourceName, int lineNumber) {
if (lineNumber < 1) {
return null;
}
SourceFile input = getSourceFileByName(sourceName);
if (input != null) {
return input.getRegion(lineNumber);
}
return null;
}
//------------------------------------------------------------------------
// Package-private helpers
//------------------------------------------------------------------------
@Override
Node getNodeForCodeInsertion(JSModule module) {
if (module == null) {
if (inputs_.length == 0) {
throw new IllegalStateException("No inputs");
}
return inputs_[0].getAstRoot(this);
}
List<CompilerInput> inputs = module.getInputs();
if (inputs.size() > 0) {
return inputs.get(0).getAstRoot(this);
}
for (JSModule m : getModuleGraph().getTransitiveDepsDeepestFirst(module)) {
inputs = m.getInputs();
if (inputs.size() > 0) {
return inputs.get(0).getAstRoot(this);
}
}
throw new IllegalStateException("Root module has no inputs");
}
public SourceMap getSourceMap() {
return sourceMap_;
}
VariableMap getVariableMap() {
return getPassConfig().getIntermediateState().variableMap;
}
VariableMap getPropertyMap() {
return getPassConfig().getIntermediateState().propertyMap;
}
CompilerOptions getOptions() {
return options_;
}
FunctionInformationMap getFunctionalInformationMap() {
return functionInformationMap_;
}
/**
* Sets the logging level for the com.google.javascript.jscomp package.
*/
public static void set
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>/*
* Copyright 2009 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.javascript.jscomp.parsing.ParserRunner;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import java.io.IOException;
import java.util.logging.Logger;
/**
* Generates an AST for a JavaScript source file.
*
*
*/
public class JsAst implements SourceAst {
private static final Logger logger_ = Logger.getLogger(JsAst.class.getName());
private static final long serialVersionUID = 1L;
private transient SourceFile sourceFile;
private String fileName;
private Node root;
public JsAst(SourceFile sourceFile) {
this.sourceFile = sourceFile;
this.fileName = sourceFile.getName();
}
@Override
public Node getAstRoot(AbstractCompiler compiler) {
if (root == null) {
createAst(compiler);
}
return root;
}
@Override
public void clearAst() {
root = null;
// While we're at it, clear out any saved text in the source file on
// the assumption that if we're dumping the parse tree, then we probably
// assume regenerating everything else is a smart idea also.
sourceFile.clearCachedSource();
}
@Override
public SourceFile getSourceFile() {
return sourceFile;
}
@Override
public void setSourceFile(SourceFile file) {
Preconditions.checkState(fileName.equals(file.getName()));
sourceFile = file;
}
private void createAst(AbstractCompiler compiler)
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS> {
try {
parse(compiler, sourceFile.getName(), sourceFile.getCode());
} catch (IOException e) {
compiler.report(
JSError.make(AbstractCompiler.READ_ERROR, sourceFile.getName()));
}
}
private void parse(AbstractCompiler compiler, String sourceName,
String sourceStr) {
try {
logger_.fine("Parsing: " + sourceName);
root = ParserRunner.parse(sourceName, sourceStr,
compiler.getParserConfig(),
compiler.getDefaultErrorReporter(),
logger_);
} catch (IOException e) {
compiler.report(JSError.make(AbstractCompiler.READ_ERROR, sourceName));
}
if (root == null || compiler.hasHaltingErrors()) {
// There was a parse error or IOException, so use a dummy block.
root = new Node(Token.BLOCK);
} else {
compiler.prepareAst(root);
}
// Set the source name so that the compiler passes can track
// the source file and module.
root.putProp(Node.SOURCENAME_PROP, sourceName);
}
}
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>String propertyName) {
return hasProperty(propertyName);
}
/** Returns the names of all the properties directly on this type. */
public Set<String> getOwnPropertyNames() {
return new HashSet<String>();
}
/**
* Checks whether the property's type is inferred.
*/
public abstract boolean isPropertyTypeInferred(String propertyName);
/**
* Checks whether the property's type is declared.
*/
public abstract boolean isPropertyTypeDeclared(String propertyName);
/**
* Whether the given property is declared on this object.
*/
boolean hasOwnDeclaredProperty(String name) {
return hasOwnProperty(name) && isPropertyTypeDeclared(name);
}
/** Checks whether the property was defined in the externs. */
public boolean isPropertyInExterns(String propertyName) {
return false;
}
/**
* Gets the number of properties of this object.
*/
public abstract int getPropertiesCount();
/**
* Returns a list of properties defined or inferred on this type and any of
* its supertypes.
*/
public Set<String> getPropertyNames() {
Set<String> props = Sets.newHashSet();
collectPropertyNames(props);
return props;
}
/**
* Adds any properties defined on this type or its supertypes to the set.
*/
abstract void collectPropertyNames(Set<String> props);
@Override
public <T> T visit(Visitor<T> visitor) {
return visitor.caseObjectType(this);
}
/**
* Checks that the prototype is an implicit prototype of this object. Since
* each object has an implicit prototype, an implicit prototype's
* implicit prototype is also this implicit prototype's.
*
* @param prototype any prototype based object
*
* @return {@code true} if {@code prototype} is {@code equal} to any
* object in this object's implicit prototype chain.
*/
final boolean isImplicitPrototype(ObjectType prototype) {
for (ObjectType current = this;
current != null;
current = current.getImplicitPrototype()) {
if (current.equals(prototype)) {
return true;
}
}
return false;
}
@Override
public BooleanLiteralSet getPossibleToBooleanOutcomes() {
return BooleanLiteralSet.TRUE;
}
/**
* We treat this as the unknown
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS> type if any of its implicit prototype
* properties is unknown.
*/
@Override
public boolean isUnknownType() {
// If the object is unknown now, check the supertype again,
// because it might have been resolved since the last check.
if (unknown) {
ObjectType implicitProto = getImplicitPrototype();
if (implicitProto == null ||
implicitProto.isNativeObjectType()) {
unknown = false;
} else {
unknown = implicitProto.isUnknownType();
}
}
return unknown;
}
@Override
public boolean isObject() {
return true;
}
/**
* Returns true if any cached valeus have been set for this type. If true,
* then the prototype chain should not be changed, as it might invalidate the
* cached values.
*/
public boolean hasCachedValues() {
return !unknown;
}
/** Whether this is a built-in object. */
public boolean isNativeObjectType() {
return false;
}
/**
* A null-safe version of JSType#toObjectType.
*/
public static ObjectType cast(JSType type) {
return type == null ? null : type.toObjectType();
}
/**
* Gets the interfaces implemented by the ctor associated with this type.
* Intended to be overridden by subclasses.
*/
public Iterable<ObjectType> getCtorImplementedInterfaces() {
return ImmutableSet.of();
}
}
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>/*
* Copyright 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import java.util.Arrays;
import java.util.Collection;
import java.util.Map;
import java.util.Set;
/**
* Group a set of related diagnostic types together, so that they can
* be toggled on and off as one unit.
* @author nicksantos@google.com (Nick Santos)
*/
public class DiagnosticGroup {
// The set of types represented by this group, hashed by key.
private final Set<DiagnosticType> types;
/**
* Create a group that matches all errors of the given types.
*/
public DiagnosticGroup(DiagnosticType ...types) {
this.types = ImmutableSet.copyOf(Arrays.asList(types));
}
/**
* Create a diagnostic group with no name that only matches the given type.
*/
private DiagnosticGroup(DiagnosticType type) {
this.types = ImmutableSet.of(type);
}
// DiagnosticGroups with only a single DiagnosticType.
private static final Map<DiagnosticType, DiagnosticGroup> singletons =
Maps.newHashMap();
/** Create a diagnostic group that matches only the given type. */
static DiagnosticGroup forType(DiagnosticType type) {
if (!singletons.containsKey(type)) {
singletons.put(type, new DiagnosticGroup(type));
}
return singletons.get(type);
}
/**
* Create a composite group.
*/
public DiagnosticGroup(Diagnostic
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>Group ...groups) {
Set<DiagnosticType> set = Sets.newHashSet();
for (DiagnosticGroup group : groups) {
set.addAll(group.types);
}
this.types = ImmutableSet.copyOf(set);
}
/**
* Returns whether the given error's type matches a type
* in this group.
*/
public boolean matches(JSError error) {
return matches(error.getType());
}
/**
* Returns whether the given type matches a type in this group.
*/
public boolean matches(DiagnosticType type) {
return types.contains(type);
}
/**
* Returns whether all of the types in the given group are in this group.
*/
boolean isSubGroup(DiagnosticGroup group) {
for (DiagnosticType type : group.types) {
if (!matches(type)) {
return false;
}
}
return true;
}
/**
* Returns an iterator over all the types in this group.
*/
Collection<DiagnosticType> getTypes() {
return types;
}
}
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>
/**
* Create a named type based on the reference.
*/
public NamedType(JSTypeRegistry registry, String reference,
String sourceName, int lineno, int charno) {
super(registry, registry.getNativeObjectType(JSTypeNative.UNKNOWN_TYPE));
Preconditions.checkNotNull(reference);
this.reference = reference;
this.sourceName = sourceName;
this.lineno = lineno;
this.charno = charno;
}
@Override
public void forgiveUnknownNames() {
forgiving = true;
}
/** Returns the type to which this refers (which is unknown if unresolved). */
public JSType getReferencedType() {
return referencedType;
}
@Override
public String getReferenceName() {
return reference;
}
@Override
public String toString() {
return reference;
}
@Override
public boolean hasReferenceName() {
return true;
}
@Override
public boolean isNamedType() {
return true;
}
@Override
public boolean isNominalType() {
return true;
}
/**
* Two named types are equal if they are the same {@code ObjectType} object.
* This is complicated by the fact that equals is sometimes called before we
* have a chance to resolve the type names.
*
* @return {@code true} iff {@code that} == {@code this} or {@code that}
* is a {@link NamedType} whose reference is the same as ours,
* or {@code that} is the type we reference.
*/
@Override
public boolean equals(Object that) {
if (this == that) {
return true;
} else if (that instanceof JSType) {
ObjectType objType = ObjectType.cast((JSType) that);
if (objType != null) {
return objType.isNominalType() &&
reference.equals(objType.getReferenceName());
}
}
return false;
}
@Override
public int hashCode() {
return reference.hashCode();
}
/**
* Resolve the referenced type within the enclosing scope.
*/
@Override
JSType resolveInternal(ErrorReporter t, StaticScope<JSType> enclosing) {
// TODO(user): Investigate whether it is really necessary to keep two
// different
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>/*
* Copyright 2006 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.javascript.rhino.JSDocInfo;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.jstype.JSType;
/**
* <p>The syntactic scope creator scans the parse tree to create a Scope object
* containing all the variable declarations in that scope.</p>
*
* <p>This implementation is not thread-safe.</p>
*
*
*/
class SyntacticScopeCreator implements ScopeCreator {
private final AbstractCompiler compiler;
private Scope scope;
private String sourceName;
private final RedeclarationHandler redeclarationHandler;
// The arguments variable is special, in that it's declared in every local
// scope, but not explicitly declared.
private static final String ARGUMENTS = "arguments";
public static final DiagnosticType VAR_MULTIPLY_DECLARED_ERROR =
DiagnosticType.error(
"JSC_VAR_MULTIPLY_DECLARED_ERROR",
"Variable {0} first declared in {1}");
/**
* Creates a ScopeCreator.
*/
SyntacticScopeCreator(AbstractCompiler compiler) {
this.compiler = compiler;
this.redeclarationHandler = new DefaultRedeclarationHandler();
}
SyntacticScopeCreator(
AbstractCompiler compiler, RedeclarationHandler redeclarationHandler) {
this.compiler = compiler;
this.redeclarationHandler = redeclarationHandler;
}
public Scope createScope(Node n, Scope parent) {
sourceName =
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS> null;
if (parent == null) {
scope = new Scope(n, compiler);
} else {
scope = new Scope(parent, n);
}
scanRoot(n, parent);
sourceName = null;
Scope returnedScope = scope;
scope = null;
return returnedScope;
}
private void scanRoot(Node n, Scope parent) {
if (n.getType() == Token.FUNCTION) {
sourceName = (String) n.getProp(Node.SOURCENAME_PROP);
final Node fnNameNode = n.getFirstChild();
final Node args = fnNameNode.getNext();
final Node body = args.getNext();
// Bleed the function name into the scope, if it hasn't
// been declared in the outer scope.
String fnName = fnNameNode.getString();
if (!fnName.isEmpty() && NodeUtil.isFunctionAnonymous(n)) {
declareVar(fnName, fnNameNode, n, null, null, n);
}
// Args: Declare function variables
Preconditions.checkState(args.getType() == Token.LP);
for (Node a = args.getFirstChild(); a != null;
a = a.getNext()) {
Preconditions.checkState(a.getType() == Token.NAME);
declareVar(a.getString(), a, args, n, null, n);
}
// Body
scanVars(body, n);
} else {
// It's the global block
Preconditions.checkState(scope.getParent() == null);
scanVars(n, null);
}
}
/**
* Scans and gather variables declarations under a Node
*/
private void scanVars(Node n, Node parent) {
switch (n.getType()) {
case Token.VAR:
// Declare all variables. e.g. var x = 1, y, z;
for (Node child = n.getFirstChild();
child != null;) {
Node next = child.getNext();
Preconditions.checkState(child.getType() == Token.NAME);
String name = child.getString();
declareVar(name, child, n, parent, null, n);
child = next;
}
return;
case Token.FUNCTION:
if (NodeUtil.isFunctionAnonymous(n)) {
return;
}
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>
String fnName = n.getFirstChild().getString();
if (fnName.isEmpty()) {
// This is invalid, but allow it so the checks can catch it.
return;
}
declareVar(fnName, n.getFirstChild(), n, parent, null, n);
return; // should not examine function's children
case Token.CATCH:
Preconditions.checkState(n.getChildCount() == 3);
Preconditions.checkState(n.getFirstChild().getType() == Token.NAME);
// the first child is the catch var and the third child
// is the code block
final Node var = n.getFirstChild();
final Node block = var.getNext().getNext();
declareVar(var.getString(), var, n, parent, null, n);
scanVars(block, n);
return; // only one child to scan
case Token.SCRIPT:
sourceName = (String) n.getProp(Node.SOURCENAME_PROP);
break;
}
// Variables can only occur in statement-level nodes, so
// we only need to traverse children in a couple special cases.
if (NodeUtil.isControlStructure(n) || NodeUtil.isStatementBlock(n)) {
for (Node child = n.getFirstChild();
child != null;) {
Node next = child.getNext();
scanVars(child, n);
child = next;
}
}
}
/**
* Interface for injectable duplicate handling.
*/
interface RedeclarationHandler {
void onRedeclaration(
Scope s, String name,
Node n, Node parent, Node gramps, Node nodeWithLineNumber);
}
/**
* The default handler for duplicate declarations.
*/
private class DefaultRedeclarationHandler implements RedeclarationHandler {
public void onRedeclaration(
Scope s, String name,
Node n, Node parent, Node gramps, Node nodeWithLineNumber) {
// Don't allow multiple variables to be declared at the top level scope
if (scope.isGlobal()) {
Scope.Var origVar = scope.getVar(name);
Node origParent = origVar.getParentNode();
if (origParent.getType() == Token.CATCH &&
parent.getType() == Token.CATCH) {
// Okay, both are 'catch(x)' variables.
return
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>;
}
boolean allowDupe = false;
JSDocInfo info = n.getJSDocInfo();
if (info == null) {
info = parent.getJSDocInfo();
}
allowDupe =
info != null && info.getSuppressions().contains("duplicate");
if (!allowDupe) {
compiler.report(
JSError.make(sourceName, nodeWithLineNumber,
VAR_MULTIPLY_DECLARED_ERROR,
name,
(origVar.input != null
? origVar.input.getName()
: "??")));
}
}
}
}
/**
* Declares a variable.
*
* @param name The variable name
* @param n The node corresponding to the variable name (usually a NAME node)
* @param parent The parent node of {@code n}
* @param gramps The parent node of {@code parent}
* @param declaredType The variable's type, according to JSDoc
* @param nodeWithLineNumber The node to use to access the line number of
* the variable declaration, if needed
*/
private void declareVar(String name, Node n, Node parent,
Node gramps, JSType declaredType,
Node nodeWithLineNumber) {
if (scope.isDeclared(name, false)
|| (scope.isLocal() && name.equals(ARGUMENTS))) {
redeclarationHandler.onRedeclaration(
scope, name, n, parent, gramps, nodeWithLineNumber);
} else {
scope.declare(name, n, declaredType, compiler.getInput(sourceName));
}
}
}
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>/*
* Copyright 2009 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.jstype.FunctionType;
import com.google.javascript.rhino.jstype.JSType;
import com.google.javascript.rhino.jstype.ObjectType;
import java.nio.charset.Charset;
/**
* A code generator that outputs type annotations for functions and
* constructors.
*
*/
class TypedCodeGenerator extends CodeGenerator {
TypedCodeGenerator(CodeConsumer consumer, Charset outputCharset) {
super(consumer, outputCharset, true);
}
@Override
void add(Node n, Context context) {
Node parent = n.getParent();
if (parent.getType() == Token.BLOCK || parent.getType() == Token.SCRIPT) {
if (n.getType() == Token.FUNCTION) {
add(getFunctionAnnotation(n));
} else if (n.getType() == Token.EXPR_RESULT
&& n.getFirstChild().getType() == Token.ASSIGN) {
Node rhs = n.getFirstChild().getFirstChild();
add(getTypeAnnotation(rhs));
} else if (n.getType() == Token.VAR
&& n.getFirstChild().getFirstChild() != null
&& n.getFirstChild().getFirstChild().getType() == Token.FUNCTION) {
add(getFunctionAnnotation(n.getFirstChild().getFirstChild()));
}
}
super.add(n, context);
}
private String getTypeAnnotation(Node node) {
JSType type = node.getJSType();
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>
if (type instanceof FunctionType) {
return getFunctionAnnotation(node);
} else if (type != null && !type.isUnknownType()
&& !type.isEmptyType() && !type.isVoidType()) {
return "/** @type {" + node.getJSType() + "} */\n";
} else {
return "";
}
}
/**
* @param node A node for a function for which to generate a type annotation
*/
private String getFunctionAnnotation(Node node) {
StringBuilder sb = new StringBuilder("/**\n");
if (node.getJSType().isUnknownType()) {
return "";
}
FunctionType funType = (FunctionType) node.getJSType();
// We need to use the child nodes of the function as the nodes for the
// parameters of the function type do not have the real parameter names.
// FUNCTION
// NAME
// LP
// NAME param1
// NAME param2
Node fnNode = funType.getSource();
if (fnNode != null) {
Node paramNode = NodeUtil.getFnParameters(fnNode).getFirstChild();
// Param types
for (Node n : funType.getParameters()) {
// Bail out if the paramNode is not there.
if (paramNode == null) {
break;
}
sb.append(" * @param {" + n.getJSType() + "} ");
sb.append(paramNode.getString());
sb.append("\n");
paramNode = paramNode.getNext();
}
}
// Return type
JSType retType = funType.getReturnType();
if (retType != null && !retType.isUnknownType() && !retType.isEmptyType()) {
sb.append(" * @return {" + retType + "}\n");
}
// Constructor/interface
if (funType.isConstructor() || funType.isInterface()) {
ObjectType superInstance =
funType.getSuperClassConstructor().getInstanceType();
if (!superInstance.toString().equals("Object")) {
sb.append(" * @extends {" + superInstance + "}\n");
}
for (ObjectType interfaze : funType.getImplementedInterfaces()) {
sb.append(" * @implements {" + interfaze + "}\n");
}
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>) {
return referencedType.canAssignTo(that);
}
@Override
public boolean equals(Object that) {
if (this == that) {
return true;
}
return referencedType.equals(that);
}
@Override
public int hashCode() {
return referencedType.hashCode();
}
@Override
public String toString() {
return referencedType.toString();
}
@Override
public ObjectType getImplicitPrototype() {
return referencedType.getImplicitPrototype();
}
@Override
boolean defineProperty(String propertyName, JSType type,
boolean inferred, boolean inExterns) {
return referencedType.defineProperty(propertyName, type, inferred,
inExterns);
}
@Override
public boolean isPropertyTypeDeclared(String propertyName) {
return referencedType.isPropertyTypeDeclared(propertyName);
}
@Override
public boolean isPropertyTypeInferred(String propertyName) {
return referencedType.isPropertyTypeInferred(propertyName);
}
@Override
public boolean isPropertyInExterns(String propertyName) {
return referencedType.isPropertyInExterns(propertyName);
}
@Override
public int getPropertiesCount() {
return referencedType.getPropertiesCount();
}
@Override
protected void collectPropertyNames(Set<String> props) {
referencedType.collectPropertyNames(props);
}
@Override
public JSType findPropertyType(String propertyName) {
return referencedType.findPropertyType(propertyName);
}
@Override
public JSType getPropertyType(String propertyName) {
return referencedType.getPropertyType(propertyName);
}
@Override
public JSDocInfo getJSDocInfo() {
return referencedType.getJSDocInfo();
}
@Override
public void setJSDocInfo(JSDocInfo info) {
referencedType.setJSDocInfo(info);
}
@Override
public JSDocInfo getOwnPropertyJSDocInfo(String propertyName) {
return referencedType.getOwnPropertyJSDocInfo(propertyName);
}
@Override
public void setPropertyJSDocInfo(String propertyName, JSDocInfo info,
boolean inExterns) {
referencedType.setPropertyJSDocInfo(propertyName, info, inExterns);
}
@Override
public boolean hasProperty(String propertyName) {
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>
return referencedType.hasProperty(propertyName);
}
@Override
public boolean hasOwnProperty(String propertyName) {
return referencedType.hasOwnProperty(propertyName);
}
@Override
public Set<String> getOwnPropertyNames() {
return referencedType.getOwnPropertyNames();
}
@Override
public FunctionType getConstructor() {
return referencedType.getConstructor();
}
@Override
public JSType getParameterType() {
return referencedType.getParameterType();
}
@Override
public JSType getIndexType() {
return referencedType.getIndexType();
}
@Override
public <T> T visit(Visitor<T> visitor) {
return referencedType.visit(visitor);
}
@Override
JSType resolveInternal(ErrorReporter t, StaticScope<JSType> scope) {
referencedType = (ObjectType) referencedType.resolve(t, scope);
return this;
}
}
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>/*
* Copyright 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.JSDocInfo;
import com.google.javascript.rhino.JSDocInfo.Visibility;
import com.google.javascript.rhino.jstype.JSType;
import com.google.javascript.rhino.jstype.FunctionPrototypeType;
import com.google.javascript.rhino.jstype.FunctionType;
import com.google.javascript.rhino.jstype.ObjectType;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
/**
* A compiler pass that checks that the programmer has obeyed all the access
* control restrictions indicated by JSDoc annotations, like
* {@code @private} and {@code @deprecated}.
*
* There are two parts to this pass:
* 1) JSDoc Inference: Attaching the appropriate JSDoc to
* all programmer-defined types and properties.
* 2) Access Control Enforcement: Emitting warnings when the code does not
* obey the restrictions attached to JSTypes in step 1.
*
* Because access control restrictions are attached to type information,
* it's important that TypeCheck runs before this pass, so that all types
* are correctly resolved and propagated before this pass runs.
*
* @author nicksantos@google.com (Nick Santos)
*/
class CheckAccessControls implements ScopedCallback
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>
private JSType currentClass = null;
CheckAccessControls(AbstractCompiler compiler) {
this.compiler = compiler;
this.validator = compiler.getTypeValidator();
}
public void process(Node externs, Node root) {
NodeTraversal.traverse(compiler, root, this);
}
public void enterScope(NodeTraversal t) {
if (!t.inGlobalScope()) {
Node n = t.getScopeRoot();
Node parent = n.getParent();
if (isDeprecatedFunction(n, parent)) {
deprecatedDepth++;
}
if (methodDepth == 0) {
currentClass = getClassOfMethod(n, parent);
}
methodDepth++;
}
}
public void exitScope(NodeTraversal t) {
if (!t.inGlobalScope()) {
Node n = t.getScopeRoot();
Node parent = n.getParent();
if (isDeprecatedFunction(n, parent)) {
deprecatedDepth--;
}
methodDepth--;
if (methodDepth == 0) {
currentClass = null;
}
}
}
/**
* Gets the type of the class that "owns" a method, or null if
* we know that its un-owned.
*/
private JSType getClassOfMethod(Node n, Node parent) {
if (parent.getType() == Token.ASSIGN) {
Node lValue = parent.getFirstChild();
if (lValue.isQualifiedName()) {
if (lValue.getType() == Token.GETPROP) {
// We have an assignment of the form "a.b = ...".
JSType lValueType = lValue.getJSType();
if (lValueType != null && lValueType.isConstructor()) {
// If a.b is a constructor, then everything in this function
// belongs to the "a.b" type.
return ((FunctionType) lValueType).getInstanceType();
} else {
// If a.b is not a constructor, then treat this as a method
// of whatever type is on "a".
return normalizeClassType(lValue.getFirstChild().getJSType());
}
} else {
// We have an assignment of the form "a = ...", so pull the
// type off the "a".
return normalizeClassType(lValue.getJSType());
}
}
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS> } else if (NodeUtil.isFunctionDeclaration(n) ||
parent.getType() == Token.NAME) {
return normalizeClassType(n.getJSType());
}
return null;
}
/**
* Normalize the type of a constructor, its instance, and its prototype
* all down to the same type (the instance type).
*/
private JSType normalizeClassType(JSType type) {
if (type == null || type.isUnknownType()) {
return type;
} else if (type.isConstructor()) {
return ((FunctionType) type).getInstanceType();
} else if (type.isFunctionPrototypeType()) {
FunctionType owner = ((FunctionPrototypeType) type).getOwnerFunction();
if (owner.isConstructor()) {
return owner.getInstanceType();
}
}
return type;
}
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
public void visit(NodeTraversal t, Node n, Node parent) {
switch (n.getType()) {
case Token.NAME:
checkNameDeprecation(t, n, parent);
checkNameVisibility(t, n, parent);
break;
case Token.GETPROP:
checkPropertyDeprecation(t, n, parent);
checkPropertyVisibility(t, n, parent);
break;
case Token.NEW:
checkConstructorDeprecation(t, n, parent);
break;
}
}
/**
* Checks the given NEW node to ensure that access restrictions are obeyed.
*/
private void checkConstructorDeprecation(NodeTraversal t, Node n,
Node parent) {
JSType type = n.getJSType();
if (type != null) {
String deprecationInfo = getTypeDeprecationInfo(type);
if (deprecationInfo != null &&
shouldEmitDeprecationWarning(t, n, parent)) {
if (!deprecationInfo.isEmpty()) {
compiler.report(
JSError.make(t, n, DEPRECATED_CLASS_REASON,
type.toString(), deprecationInfo));
} else {
compiler.report(
JSError.make(t, n, DEPRECATED_CLASS, type.toString()));
}
}
}
}
/**
* Checks the given NAME node to ensure that access restrictions are obeyed.
*/
private
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>NodeTraversal t, Node name, Node parent) {
Var var = t.getScope().getVar(name.getString());
if (var != null) {
JSDocInfo docInfo = var.getJSDocInfo();
if (docInfo != null) {
// If a name is private, make sure that we're in the same file.
Visibility visibility = docInfo.getVisibility();
if (visibility == Visibility.PRIVATE &&
!t.getInput().getName().equals(docInfo.getSourceName())) {
if (docInfo.isConstructor() &&
isValidPrivateConstructorAccess(parent)) {
return;
}
compiler.report(
JSError.make(t, name, BAD_PRIVATE_GLOBAL_ACCESS,
name.getString(), docInfo.getSourceName()));
}
}
}
}
/**
* Determines whether the given property is visible in the current context.
* @param t The current traversal.
* @param getprop The getprop node.
*/
private void checkPropertyVisibility(NodeTraversal t,
Node getprop, Node parent) {
ObjectType objectType =
ObjectType.cast(dereference(getprop.getFirstChild().getJSType()));
String propertyName = getprop.getLastChild().getString();
if (objectType != null) {
// Is this a normal property access, or are we trying to override
// an existing property?
boolean isOverride = t.inGlobalScope() &&
parent.getType() == Token.ASSIGN &&
parent.getFirstChild() == getprop;
// Find the lowest property defined on a class with visibility
// information.
if (isOverride) {
objectType = objectType.getImplicitPrototype();
}
JSDocInfo docInfo = null;
for (; objectType != null;
objectType = objectType.getImplicitPrototype()) {
docInfo = objectType.getOwnPropertyJSDocInfo(propertyName);
if (docInfo != null &&
docInfo.getVisibility() != Visibility.INHERITED) {
break;
}
}
if (objectType == null) {
// We couldn't find a visibility modifier; assume it's public.
return;
}
boolean sameInput =
t.getInput().getName().equals(docInfo.getSourceName());
Visibility visibility = docInfo.getVisibility();
JSType owner
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>
}
/**
* Whether the given access of a private constructor is legal.
*
* For example,
* new PrivateCtor_(); // not legal
* PrivateCtor_.newInstance(); // legal
* x instanceof PrivateCtor_ // legal
*
* This is a weird special case, because our visibility system is inherited
* from Java, and JavaScript has no distinction between classes and
* constructors like Java does.
*
* We may want to revisit this if we decide to make the restrictions tighter.
*/
private static boolean isValidPrivateConstructorAccess(Node parent) {
return parent.getType() != Token.NEW;
}
/**
* Determines whether a deprecation warning should be emitted.
* @param t The current traversal.
* @param n The node which we are checking.
* @param parent The parent of the node which we are checking.
*/
private boolean shouldEmitDeprecationWarning(
NodeTraversal t, Node n, Node parent) {
// In the global scope, there are only two kinds of accesses that should
// be flagged for warnings:
// 1) Calls of deprecated functions and methods.
// 2) Instantiations of deprecated classes.
// For now, we just let everything else by.
if (t.inGlobalScope()) {
if (!((parent.getType() == Token.CALL && parent.getFirstChild() == n) ||
n.getType() == Token.NEW)) {
return false;
}
}
// We can always assign to a deprecated property, to keep it up to date.
if (n.getType() == Token.GETPROP && n == parent.getFirstChild() &&
NodeUtil.isAssignmentOp(parent)) {
return false;
}
return !canAccessDeprecatedTypes(t);
}
/**
* Returns whether it's currently ok to access deprecated names and
* properties.
*
* There are 3 exceptions when we're allowed to use a deprecated
* type or property:
* 1) When we're in a deprecated function.
* 2) When we're in a deprecated class.
* 3) When we're in a static method of a deprecated class.
*/
private boolean canAccessDeprecatedTypes(NodeTraversal t) {
Node scopeRoot = t.getScopeRoot();
Node scopeRootParent = scopeRoot.
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>_LOCALE_CONSTANT_NAME = "goog.LOCALE";
// Compiler errors when invalid combinations of passes are run.
static final DiagnosticType TIGHTEN_TYPES_WITHOUT_TYPE_CHECK =
DiagnosticType.error("JSC_TIGHTEN_TYPES_WITHOUT_TYPE_CHECK",
"TightenTypes requires type checking. Please use --check_types.");
static final DiagnosticType CANNOT_USE_PROTOTYPE_AND_VAR =
DiagnosticType.error("JSC_CANNOT_USE_PROTOTYPE_AND_VAR",
"Rename prototypes and inline variables cannot be used together");
// Miscellaneous errors.
static final DiagnosticType REPORT_PATH_IO_ERROR =
DiagnosticType.error("JSC_REPORT_PATH_IO_ERROR",
"Error writing compiler report to {0}");
private static final DiagnosticType INPUT_MAP_PROP_PARSE =
DiagnosticType.error("JSC_INPUT_MAP_PROP_PARSE",
"Input property map parse error: {0}");
private static final DiagnosticType INPUT_MAP_VAR_PARSE =
DiagnosticType.error("JSC_INPUT_MAP_VAR_PARSE",
"Input variable map parse error: {0}");
/**
* A global namespace to share across checking passes.
* TODO(nicksantos): This is a hack until I can get the namespace into
* the symbol table.
*/
private GlobalNamespace namespaceForChecks = null;
/**
* A type-tightener to share across optimization passes.
*/
private TightenTypes tightenTypes = null;
/** Names exported by goog.exportSymbol. */
private Set<String> exportedNames = null;
/**
* Ids for cross-module method stubbing, so that each method has
* a unique id.
*/
private CrossModuleMethodMotion.IdGenerator crossModuleIdGenerator =
new CrossModuleMethodMotion.IdGenerator();
/**
* Keys are arguments passed to getCssName() found during compilation; values
* are the number of times the key appeared as an argument to getCssName().
*/
private Map<String, Integer> cssNames = null;
/** The variable renaming map */
private VariableMap variableMap = null;
/** The property renaming map */
private VariableMap propertyMap = null;
/** The naming map for anonymous functions */
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS> private VariableMap anonymousFunctionNameMap = null;
/** Fully qualified function names and globally unique ids */
private FunctionNames functionNames = null;
public DefaultPassConfig(CompilerOptions options) {
super(options);
}
@Override
State getIntermediateState() {
return new State(
cssNames == null ? null : Maps.newHashMap(cssNames),
exportedNames == null ? null :
Collections.unmodifiableSet(exportedNames),
crossModuleIdGenerator, variableMap, propertyMap,
anonymousFunctionNameMap, functionNames);
}
@Override
void setIntermediateState(State state) {
this.cssNames = state.cssNames == null ? null :
Maps.newHashMap(state.cssNames);
this.exportedNames = state.exportedNames == null ? null :
Sets.newHashSet(state.exportedNames);
this.crossModuleIdGenerator = state.crossModuleIdGenerator;
this.variableMap = state.variableMap;
this.propertyMap = state.propertyMap;
this.anonymousFunctionNameMap = state.anonymousFunctionNameMap;
this.functionNames = state.functionNames;
}
@Override
protected List<PassFactory> getChecks() {
List<PassFactory> checks = Lists.newArrayList();
if (options.nameAnonymousFunctionsOnly) {
if (options.anonymousFunctionNaming ==
AnonymousFunctionNamingPolicy.MAPPED) {
checks.add(nameMappedAnonymousFunctions);
} else if (options.anonymousFunctionNaming ==
AnonymousFunctionNamingPolicy.UNMAPPED) {
checks.add(nameUnmappedAnonymousFunctions);
}
return checks;
}
if (options.checkSuspiciousCode) {
checks.add(suspiciousCode);
}
if (options.checkControlStructures) {
checks.add(checkControlStructures);
}
if (options.checkRequires.isOn()) {
checks.add(checkRequires);
}
if (options.checkProvides.isOn()) {
checks.add(checkProvides);
}
// The following passes are more like "preprocessor" passes.
// It's important that they run before most checking passes.
// Perhaps this method should be renamed?
if (options.generateExports) {
checks.add(generateExports);
}
if (options.exportTestFunctions) {
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>
checks.add(exportTestFunctions);
}
if (options.closurePass) {
checks.add(closurePrimitives.makeOneTimePass());
}
if (options.closurePass && options.checkMissingGetCssNameLevel.isOn()) {
checks.add(closureCheckGetCssName);
}
if (options.closurePass) {
checks.add(closureReplaceGetCssName);
}
if (options.syntheticBlockStartMarker != null) {
// This pass must run before the first fold constants pass.
checks.add(createSyntheticBlocks);
}
// All passes must run the variable check. This synthesizes
// variables later so that the compiler doesn't crash. It also
// checks the externs file for validity. If you don't want to warn
// about missing variable declarations, we shut that specific
// error off.
WarningsGuard warningsGuard = options.getWarningsGuard();
if (!options.checkSymbols &&
(warningsGuard == null || !warningsGuard.disables(
DiagnosticGroups.CHECK_VARIABLES))) {
options.setWarningLevel(DiagnosticGroups.CHECK_VARIABLES,
CheckLevel.OFF);
}
checks.add(checkVars);
if (options.checkShadowVars.isOn()) {
checks.add(checkShadowVars);
}
if (options.aggressiveVarCheck.isOn()) {
checks.add(checkVariableReferences);
}
// This pass should run before types are assigned.
if (options.processObjectPropertyString) {
checks.add(objectPropertyStringPreprocess);
}
// DiagnosticGroups override the plain checkTypes option.
if (options.enables(DiagnosticGroups.CHECK_TYPES)) {
options.checkTypes = true;
} else if (options.disables(DiagnosticGroups.CHECK_TYPES)) {
options.checkTypes = false;
}
// Type-checking already does more accurate method arity checking, so don't
// do legacy method arity checking unless checkTypes is OFF.
if (options.checkTypes) {
checks.add(resolveTypes.makeOneTimePass());
checks.add(inferTypes.makeOneTimePass());
checks.add(checkTypes.makeOneTimePass());
} else {
if (options.checkFunctions.isOn()) {
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS> checks.add(checkFunctions);
}
if (options.checkMethods.isOn()) {
checks.add(checkMethods);
}
}
if (options.checkUnreachableCode.isOn() ||
(options.checkTypes && options.checkMissingReturn.isOn())) {
checks.add(checkControlFlow);
}
// CheckAccessControls only works if check types is on.
if (options.enables(DiagnosticGroups.ACCESS_CONTROLS)
&& options.checkTypes) {
checks.add(checkAccessControls);
}
if (options.checkGlobalNamesLevel.isOn()) {
checks.add(checkGlobalNames);
}
if (options.checkUndefinedProperties.isOn() ||
options.checkUnusedPropertiesEarly) {
checks.add(checkSuspiciousProperties);
}
if (options.checkCaja || options.checkEs5Strict) {
checks.add(checkStrictMode);
}
// Defines in code always need to be processed.
checks.add(processDefines);
if (options.instrumentationTemplate != null ||
options.recordFunctionInformation) {
checks.add(computeFunctionNames);
}
assertAllOneTimePasses(checks);
return checks;
}
@Override
protected List<PassFactory> getOptimizations() {
List<PassFactory> passes = Lists.newArrayList();
// TODO(nicksantos): The order of these passes makes no sense, and needs
// to be re-arranged.
if (options.runtimeTypeCheck) {
passes.add(runtimeTypeCheck);
}
passes.add(createEmptyPass("beforeStandardOptimizations"));
if (!options.idGenerators.isEmpty()) {
passes.add(replaceIdGenerators);
}
// Optimizes references to the arguments variable.
if (options.optimizeArgumentsArray) {
passes.add(optimizeArgumentsArray);
}
// Remove all parameters that are constants or unused.
if (options.optimizeParameters) {
passes.add(removeUselessParameters);
}
// Abstract method removal works best on minimally modified code, and also
// only needs to run once.
if (options.closurePass && options.removeAbstractMethods) {
passes.add(removeAbstractMethods);
}
// Collapsing properties can undo constant
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS> inlining, so we do this before
// the main optimization loop.
if (options.collapseProperties) {
passes.add(collapseProperties);
}
// Tighten types based on actual usage.
if (options.tightenTypes) {
passes.add(tightenTypesBuilder);
}
// Property disambiguation should only run once and needs to be done
// soon after type checking, both so that it can make use of type
// information and so that other passes can take advantage of the renamed
// properties.
if (options.disambiguateProperties) {
passes.add(disambiguateProperties);
}
if (options.computeFunctionSideEffects) {
passes.add(markPureFunctions);
} else if (options.markNoSideEffectCalls) {
// TODO(user) The properties that this pass adds to CALL and NEW
// AST nodes increase the AST's in-memory size. Given that we are
// already running close to our memory limits, we could run into
// trouble if we end up using the @nosideeffects annotation a lot
// or compute @nosideeffects annotations by looking at function
// bodies. It should be easy to propagate @nosideeffects
// annotations as part of passes that depend on this property and
// store the result outside the AST (which would allow garbage
// collection once the pass is done).
passes.add(markNoSideEffectCalls);
}
if (options.chainCalls) {
passes.add(chainCalls);
}
// Constant checking must be done after property collapsing because
// property collapsing can introduce new constants (e.g. enum values).
if (options.inlineConstantVars) {
passes.add(checkConsts);
}
// The Caja library adds properties to Object.prototype, which breaks
// most for-in loops. This adds a check to each loop that skips
// any property matching /___$/.
if (options.ignoreCajaProperties) {
passes.add(ignoreCajaProperties);
}
assertAllOneTimePasses(passes);
if (options.smartNameRemoval || options.reportPath != null) {
passes.addAll(getCodeRemovingPasses());
passes.add(smartNamePass);
}
// TODO(user): This forces a
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS> first crack at crossModuleCodeMotion
// before devirtualization. Once certain functions are devirtualized,
// it confuses crossModuleCodeMotion ability to recognized that
// it is recursive.
// TODO(user): This is meant for a temporary quick win.
// In the future, we might want to improve our analysis in
// CrossModuleCodeMotion so we don't need to do this.
if (options.crossModuleCodeMotion) {
passes.add(crossModuleCodeMotion);
}
// Method devirtualization benefits from property disambiguiation so
// it should run after that pass but before passes that do
// optimizations based on global names (like cross module code motion
// and inline functions). Smart Name Removal does better if run before
// this pass.
if (options.devirtualizePrototypeMethods) {
passes.add(devirtualizePrototypeMethods);
}
if (options.customPasses != null) {
passes.add(getCustomPasses(
CustomPassExecutionTime.BEFORE_OPTIMIZATION_LOOP));
}
passes.add(createEmptyPass("beforeMainOptimizations"));
passes.addAll(getMainOptimizationLoop());
passes.add(createEmptyPass("beforeModuleMotion"));
if (options.crossModuleCodeMotion) {
passes.add(crossModuleCodeMotion);
}
if (options.crossModuleMethodMotion) {
passes.add(crossModuleMethodMotion);
}
passes.add(createEmptyPass("afterModuleMotion"));
// Some optimizations belong outside the loop because running them more
// than once would either have no benefit or be incorrect.
if (options.customPasses != null) {
passes.add(getCustomPasses(
CustomPassExecutionTime.AFTER_OPTIMIZATION_LOOP));
}
if (options.flowSensitiveInlineVariables) {
passes.add(flowSensitiveInlineVariables);
// After inlining some of the variable uses, some variables are unused.
// Re-run remove unused vars to clean it up.
if (options.removeUnusedVars) {
passes.add(removeUnusedVars);
}
}
if (options.collapseAnonymousFunctions) {
passes.add(collapseAnonymousFunctions);
}
// Move functions before extracting prototype member declarations.
if (options.moveFunctionDeclarations) {
passes
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>.add(moveFunctionDeclarations);
}
if (options.anonymousFunctionNaming ==
AnonymousFunctionNamingPolicy.MAPPED) {
passes.add(nameMappedAnonymousFunctions);
}
// The mapped name anonymous function pass makes use of information that
// the extract prototype member declarations pass removes so the former
// happens before the latter.
//
// Extracting prototype properties screws up the heuristic renaming
// policies, so never run it when those policies are requested.
if (options.extractPrototypeMemberDeclarations &&
(options.propertyRenaming != PropertyRenamingPolicy.HEURISTIC &&
options.propertyRenaming !=
PropertyRenamingPolicy.AGGRESSIVE_HEURISTIC)) {
passes.add(extractPrototypeMemberDeclarations);
}
if (options.coalesceVariableNames) {
passes.add(coalesceVariableNames);
}
if (options.ambiguateProperties &&
(options.propertyRenaming == PropertyRenamingPolicy.ALL_UNQUOTED)) {
passes.add(ambiguateProperties);
}
if (options.propertyRenaming != PropertyRenamingPolicy.OFF) {
passes.add(renameProperties);
}
// Reserve global names added to the "windows" object.
if (options.reserveRawExports) {
passes.add(gatherRawExports);
}
// This comes after property renaming because quoted property names must
// not be renamed.
if (options.convertToDottedProperties) {
passes.add(convertToDottedProperties);
}
// Property renaming must happen before this pass runs since this
// pass may convert dotted properties into quoted properties. It
// is beneficial to run before alias strings, alias keywords and
// variable renaming.
if (options.rewriteFunctionExpressions) {
passes.add(rewriteFunctionExpressions);
}
// This comes after converting quoted property accesses to dotted property
// accesses in order to avoid aliasing property names.
if (!options.aliasableStrings.isEmpty() || options.aliasAllStrings) {
passes.add(aliasStrings);
}
if (options.aliasExternals) {
passes.add(aliasExternals);
}
if (options.aliasKeywords) {
passes.add(aliasKeywords);
}
if (options.collapseVariableDeclarations) {
passes.add(collapseVariableDeclarations);
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>
}
passes.add(denormalize);
if (options.instrumentationTemplate != null) {
passes.add(instrumentFunctions);
}
if (options.variableRenaming != VariableRenamingPolicy.ALL) {
// If we're leaving some (or all) variables with their old names,
// then we need to undo any of the markers we added for distinguishing
// local variables ("$$1").
passes.add(invertContextualRenaming);
}
if (options.variableRenaming != VariableRenamingPolicy.OFF) {
passes.add(renameVars);
}
// This pass should run after names stop changing.
if (options.processObjectPropertyString) {
passes.add(objectPropertyStringPostprocess);
}
if (options.labelRenaming) {
passes.add(renameLabels);
}
if (options.anonymousFunctionNaming ==
AnonymousFunctionNamingPolicy.UNMAPPED) {
passes.add(nameUnmappedAnonymousFunctions);
}
// Safety check
if (options.checkSymbols) {
passes.add(sanityCheckVars);
}
return passes;
}
/** Creates the passes for the main optimization loop. */
private List<PassFactory> getMainOptimizationLoop() {
List<PassFactory> passes = Lists.newArrayList();
if (options.inlineGetters) {
passes.add(inlineGetters);
}
passes.addAll(getCodeRemovingPasses());
if (options.inlineFunctions || options.inlineLocalFunctions) {
passes.add(inlineFunctions);
}
if (options.removeUnusedVars) {
if (options.deadAssignmentElimination) {
passes.add(deadAssignmentsElimination);
}
passes.add(removeUnusedVars);
}
assertAllLoopablePasses(passes);
return passes;
}
/** Creates several passes aimed at removing code. */
private List<PassFactory> getCodeRemovingPasses() {
List<PassFactory> passes = Lists.newArrayList();
if (options.inlineVariables || options.inlineLocalVariables) {
passes.add(inlineVariables);
} else if (options.inlineConstantVars) {
passes.add(inlineConstants);
}
if (options.removeConstantExpressions) {
passes.add(removeConstantExpressions);
}
if
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS> (options.foldConstants) {
// These used to be one pass.
passes.add(minimizeExitPoints);
passes.add(foldConstants);
}
if (options.removeDeadCode) {
passes.add(removeUnreachableCode);
}
if (options.removeUnusedPrototypeProperties) {
passes.add(removeUnusedPrototypeProperties);
}
assertAllLoopablePasses(passes);
return passes;
}
/**
* Checks for code that is probably wrong (such as stray expressions).
*/
// TODO(bolinfest): Write a CompilerPass for this.
final PassFactory suspiciousCode =
new PassFactory("suspiciousCode", true) {
@Override
protected CompilerPass createInternal(final AbstractCompiler compiler) {
List<Callback> sharedCallbacks = Lists.newArrayList();
sharedCallbacks.add(new CheckAccidentalSemicolon(CheckLevel.WARNING));
sharedCallbacks.add(new CheckSideEffects(CheckLevel.WARNING));
if (options.checkGlobalThisLevel.isOn()) {
sharedCallbacks.add(
new CheckGlobalThis(compiler, options.checkGlobalThisLevel));
}
return combineChecks(compiler, sharedCallbacks);
}
};
/** Verify that all the passes are one-time passes. */
private void assertAllOneTimePasses(List<PassFactory> passes) {
for (PassFactory pass : passes) {
Preconditions.checkState(pass.isOneTimePass());
}
}
/** Verify that all the passes are multi-run passes. */
private void assertAllLoopablePasses(List<PassFactory> passes) {
for (PassFactory pass : passes) {
Preconditions.checkState(!pass.isOneTimePass());
}
}
/** Checks for validity of the control structures. */
private final PassFactory checkControlStructures =
new PassFactory("checkControlStructures", true) {
@Override
protected CompilerPass createInternal(AbstractCompiler compiler) {
return new ControlStructureCheck(compiler);
}
};
/** Checks that all constructed classes are goog.require()d. */
private final PassFactory checkRequires =
new PassFactory("checkRequires", true) {
@Override
protected CompilerPass createInternal(AbstractCompiler compiler) {
return new CheckRequiresForConstructors(compiler, options.checkRequires
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>);
}
};
/** Makes sure @constructor is paired with goog.provides(). */
private final PassFactory checkProvides =
new PassFactory("checkProvides", true) {
@Override
protected CompilerPass createInternal(AbstractCompiler compiler) {
return new CheckProvides(compiler, options.checkProvides);
}
};
private static final DiagnosticType GENERATE_EXPORTS_ERROR =
DiagnosticType.error(
"JSC_GENERATE_EXPORTS_ERROR",
"Exports can only be generated if export symbol/property " +
"functions are set.");
/** Generates exports for @export annotations. */
private final PassFactory generateExports =
new PassFactory("generateExports", true) {
@Override
protected CompilerPass createInternal(AbstractCompiler compiler) {
CodingConvention convention = compiler.getCodingConvention();
if (convention.getExportSymbolFunction() != null &&
convention.getExportPropertyFunction() != null) {
return new GenerateExports(compiler,
convention.getExportSymbolFunction(),
convention.getExportPropertyFunction());
} else {
return new ErrorPass(compiler, GENERATE_EXPORTS_ERROR);
}
}
};
/** Generates exports for functions associated with JSUnit. */
private final PassFactory exportTestFunctions =
new PassFactory("exportTestFunctions", true) {
@Override
protected CompilerPass createInternal(AbstractCompiler compiler) {
CodingConvention convention = compiler.getCodingConvention();
if (convention.getExportSymbolFunction() != null) {
return new ExportTestFunctions(compiler,
convention.getExportSymbolFunction());
} else {
return new ErrorPass(compiler, GENERATE_EXPORTS_ERROR);
}
}
};
/** Raw exports processing pass. */
final PassFactory gatherRawExports =
new PassFactory("gatherRawExports", false) {
@Override
protected CompilerPass createInternal(AbstractCompiler compiler) {
final GatherRawExports pass = new GatherRawExports(
compiler);
return new CompilerPass() {
@Override
public void process(Node externs, Node root) {
pass.process(externs, root);
if (exportedNames == null) {
exportedNames = Sets.newHashSet();
}
exportedNames.addAll(pass.getExportedVariableNames());
}
};
}
};
/** Closure pre
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>(AbstractCompiler compiler) {
return new GlobalTypeResolver(compiler);
}
};
/** Rusn type inference. */
private final PassFactory inferTypes =
new PassFactory("inferTypes", false) {
@Override
protected CompilerPass createInternal(final AbstractCompiler compiler) {
return new CompilerPass() {
@Override
public void process(Node externs, Node root) {
Preconditions.checkNotNull(topScope);
Preconditions.checkNotNull(typedScopeCreator);
makeTypeInference(compiler).process(externs, root);
}
};
}
};
/** Checks type usage */
private final PassFactory checkTypes =
new PassFactory("checkTypes", false) {
@Override
protected CompilerPass createInternal(final AbstractCompiler compiler) {
return new CompilerPass() {
@Override
public void process(Node externs, Node root) {
Preconditions.checkNotNull(topScope);
Preconditions.checkNotNull(typedScopeCreator);
TypeCheck check = makeTypeCheck(compiler);
check.process(externs, root);
compiler.getErrorManager().setTypedPercent(check.getTypedPercent());
}
};
}
};
/**
* Checks possible execution paths of the program for problems: missing return
* statements and dead code.
*/
private final PassFactory checkControlFlow =
new PassFactory("checkControlFlow", true) {
@Override
protected CompilerPass createInternal(AbstractCompiler compiler) {
List<Callback> callbacks = Lists.newArrayList();
if (options.checkUnreachableCode.isOn()) {
callbacks.add(
new CheckUnreachableCode(compiler, options.checkUnreachableCode));
}
if (options.checkMissingReturn.isOn() && options.checkTypes) {
callbacks.add(
new CheckMissingReturn(compiler, options.checkMissingReturn));
}
return combineChecks(compiler, callbacks);
}
};
/** Checks access controls. Depends on type-inference. */
private final PassFactory checkAccessControls =
new PassFactory("checkAccessControls", true) {
@Override
protected CompilerPass createInternal(AbstractCompiler compiler) {
return new CheckAccessControls(compiler);
}
};
/** Executes the given callbacks with a {@link CombinedCompilerPass}. */
private static CompilerPass combineChecks(AbstractCompiler compiler,
List<Callback
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>
return options.propertyRenaming == PropertyRenamingPolicy.HEURISTIC ||
options.propertyRenaming ==
PropertyRenamingPolicy.AGGRESSIVE_HEURISTIC;
}
/** Create a compiler pass that runs the given passes in serial. */
private static CompilerPass runInSerial(final CompilerPass ... passes) {
return runInSerial(Lists.newArrayList(passes));
}
/** Create a compiler pass that runs the given passes in serial. */
private static CompilerPass runInSerial(
final Collection<CompilerPass> passes) {
return new CompilerPass() {
@Override public void process(Node externs, Node root) {
for (CompilerPass pass : passes) {
pass.process(externs, root);
}
}
};
}
@VisibleForTesting
static Map<String, Node> getAdditionalReplacements(
CompilerOptions options) {
Map<String, Node> additionalReplacements = Maps.newHashMap();
if (options.markAsCompiled || options.closurePass) {
additionalReplacements.put(COMPILED_CONSTANT_NAME, new Node(Token.TRUE));
}
if (options.closurePass && options.locale != null) {
additionalReplacements.put(CLOSURE_LOCALE_CONSTANT_NAME,
Node.newString(options.locale));
}
return additionalReplacements;
}
/** A compiler pass that marks pure functions. */
private static class PureFunctionMarker implements CompilerPass {
private final AbstractCompiler compiler;
private final String reportPath;
private final boolean useNameReferenceGraph;
PureFunctionMarker(AbstractCompiler compiler, String reportPath,
boolean useNameReferenceGraph) {
this.compiler = compiler;
this.reportPath = reportPath;
this.useNameReferenceGraph = useNameReferenceGraph;
}
@Override
public void process(Node externs, Node root) {
DefinitionProvider definitionProvider = null;
if (useNameReferenceGraph) {
NameReferenceGraphConstruction graphBuilder =
new NameReferenceGraphConstruction(compiler);
graphBuilder.process(externs, root);
definitionProvider = graphBuilder.getNameReferenceGraph();
} else {
SimpleDefinitionFinder defFinder = new SimpleDefinitionFinder(compiler);
defFinder.process(externs, root);
definitionProvider = defFinder;
}
PureFunction
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS> determining provided dependencies amongst different
* js scripts.
*/
public String extractClassNameIfProvide(Node node, Node parent);
/**
* Convenience method for determining required dependencies amongst different
* js scripts.
*/
public String extractClassNameIfRequire(Node node, Node parent);
/**
* Function name used when exporting properties.
* Signature: fn(object, publicName, symbol).
* @return function name.
*/
public String getExportPropertyFunction();
/**
* Function name used when exporting symbols.
* Signature: fn(publicPath, object).
* @return function name.
*/
public String getExportSymbolFunction();
/**
* Checks if the given CALL node is forward-declaring any types,
* and returns the name of the types if it is.
*/
public List<String> identifyTypeDeclarationCall(Node n);
/**
* Checks if the given ASSIGN node is a typedef, and returns the
* name of the type if it is.
*/
public String identifyTypeDefAssign(Node n);
/**
* In many JS libraries, the function that produces inheritance also
* adds properties to the superclass and/or subclass.
*/
public void applySubclassRelationship(FunctionType parentCtor,
FunctionType childCtor, SubclassType type);
/**
* Function name for abstract methods. An abstract method can be assigned to
* an interface method instead of an anonymous function in order to avoid
* linter warnings produced by assigning a function without a return value
* where a return value is expected.
* @return function name.
*/
public String getAbstractMethodName();
/**
* Checks if the given method defines a singleton getter, and if it does,
* returns the name of the class with the singleton getter. By default, always
* returns null. Meant to be overridden by subclasses.
*
* @param callNode A CALL node.
*/
public String getSingletonGetterClassName(Node callNode);
/**
* In many JS libraries, the function that adds a singleton getter to a class
* adds properties to the class.
*/
public void applySingletonGetter(FunctionType functionType,
FunctionType getterType, ObjectType objectType);
public DelegateRelationship getDelegateRelationship(Node callNode);
/**
* In many JS libraries, the function that creates a delegate relationship
* also adds properties to the deleg
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>/*
* Copyright 2004 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.javascript.rhino.Node;
/**
* Abstracted consumer of the CodeGenerator output.
*
* @see CodeGenerator
* @see CodePrinter
* @see InlineCostEstimator
*
*
*
*/
abstract class CodeConsumer {
boolean statementNeedsEnded = false;
boolean statementStarted = false;
boolean sawFunction = false;
/**
* Starts the source mapping for the given
* node at the current position.
*/
void startSourceMapping(Node node) {
}
/**
* Finishes the source mapping for the given
* node at the current position.
*/
void endSourceMapping(Node node) {
}
/**
* Generates the source map from the given code consumer,
* appending the information it saved to the SourceMap
* object given.
*/
void generateSourceMap(SourceMap map){
}
/**
* Returns the current length of the buffer in which
* the generated code is being placed.
*/
abstract int getCurrentBufferLength();
/**
* Returns the current character position on the current
* line in the generated code.
*/
abstract int getCurrentCharIndex();
/**
* Returns the current line in the generated code.
*/
abstract int getCurrentLineIndex();
/**
* Provides a means of interrupting the CodeGenerator. Derived classes should
* return false to stop further processing.
*/
boolean continueProcessing() {
return true;
}
/**
* Retrieve the last character of the last string sent to append.
*/
abstract char getLastChar();
void addIdentifier(String identifier) {
add
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>(identifier);
}
/**
* Appends a string to the code, keeping track of the current line length.
*
* NOTE: the string must be a complete token--partial strings or
* partial regexes will run the risk of being split across lines.
*
* Do not directly append newlines with this method. Instead use
* {@link #startNewLine}.
*/
abstract void append(String str);
void appendBlockStart() {
append("{");
}
void appendBlockEnd() {
append("}");
}
void startNewLine() {
}
void maybeLineBreak() {
maybeCutLine();
}
void maybeCutLine() {
}
void endLine() {
}
void notePreferredLineBreak() {
}
void beginBlock() {
if (statementNeedsEnded) {
append(";");
maybeLineBreak();
}
appendBlockStart();
endLine();
statementNeedsEnded = false;
}
void endBlock() {
endBlock(false);
}
void endBlock(boolean statementContext) {
appendBlockEnd();
if (statementContext) {
endLine();
}
statementNeedsEnded = false;
}
void listSeparator() {
add(",");
maybeLineBreak();
}
/**
* Indicates the end of a statement and a ';' may need to be added.
* But we don't add it now, in case we're at the end of a block (in which
* case we don't have to add the ';').
* See maybeEndStatement()
*/
void endStatement() {
endStatement(false);
}
void endStatement(boolean needSemiColon) {
if (needSemiColon) {
append(";");
maybeLineBreak();
statementNeedsEnded = false;
} else if (statementStarted) {
statementNeedsEnded = true;
}
}
/**
* This is to be called when we're in a statement. If the prev statement
* needs to be ended, add a ';'.
*/
void maybeEndStatement() {
// Add a ';' if we need to.
if (statementNeedsEnded) {
append(";");
maybeLineBreak();
endLine();
statementNeedsEnded = false;
}
statementStarted = true;
}
void endFunction() {
endFunction(false
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>);
}
void endFunction(boolean statementContext) {
sawFunction = true;
if (statementContext) {
endLine();
}
}
void beginCaseBody() {
append(":");
}
void endCaseBody() {
}
void add(String newcode) {
maybeEndStatement();
if (newcode.length() == 0) {
return;
}
char c = newcode.charAt(0);
if ((isWordChar(c) || c == '\\') &&
isWordChar(getLastChar())) {
// need space to separate. This is not pretty printing.
// For example: "return foo;"
append(" ");
}
append(newcode);
}
void appendOp(String op, boolean binOp) {
append(op);
}
void addOp(String op, boolean binOp) {
maybeEndStatement();
char first = op.charAt(0);
char prev = getLastChar();
if ((first == '+' || first == '-') && prev == first) {
// This is not pretty printing. This is to prevent misparsing of
// things like "x + ++y" or "x++ + ++y"
append(" ");
} else if (Character.isLetter(first) &&
isWordChar(prev)) {
// Make sure there is a space after e.g. instanceof , typeof
append(" ");
} else if (prev == '-' && first == '>') {
// Make sure that we don't emit -->
append(" ");
}
// Allow formating around the operator.
appendOp(op, binOp);
// Line breaking after an operator is always safe. Line breaking before an
// operator on the other hand is not. We only line break after a bin op
// because it looks strange.
if (binOp) {
maybeCutLine();
}
}
void addNumber(double x) {
// This is not pretty printing. This is to prevent misparsing of x- -4 as
// x--4 (which is a syntax error).
char prev = getLastChar();
if (x < 0 && prev == '-') {
add(" ");
}
if ((long) x == x) {
long value = (long) x;
long mantissa = value;
int exp =
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS> 0;
if (x >= 100) {
while (mantissa / 10 * Math.pow(10, exp + 1) == value) {
mantissa /= 10;
exp++;
}
}
if (exp > 2) {
add(Long.toString(mantissa) + "E" + Integer.toString(exp));
} else {
add(Long.toString(value));
}
} else {
add(String.valueOf(x));
}
}
static boolean isWordChar(char ch) {
return (ch == '_' ||
ch == '$' ||
Character.isLetterOrDigit(ch));
}
/**
* If the body of a for loop or the then clause of an if statement has
* a single statement, should it be wrapped in a block? Doing so can
* help when pretty-printing the code, and permits putting a debugging
* breakpoint on the statement inside the condition.
*
* @return {@boolean true} if such expressions should be wrapped
*/
boolean shouldPreserveExtraBlocks() {
return false;
}
}
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS> {@code UnionType} implements a common JavaScript idiom in which the
* code is specifically designed to work with multiple input types. Because
* JavaScript always knows the runtime type of an object value, this is safer
* than a C union.<p>
*
* For instance, values of the union type {@code (String,boolean)} can be of
* type {@code String} or of type {@code boolean}. The commutativity of the
* statement is captured by making {@code (String,boolean)} and
* {@code (boolean,String)} equal.<p>
*
* The implementation of this class prevents the creation of nested
* unions.<p>
*/
public class UnionType extends JSType {
private static final long serialVersionUID = 1L;
Set<JSType> alternates;
private final int hashcode;
/**
* Creates a union type.
*
* @param alternates the alternates of the union
*/
UnionType(JSTypeRegistry registry, Set<JSType> alternates) {
super(registry);
this.alternates = alternates;
this.hashcode = this.alternates.hashCode();
}
/**
* Gets the alternate types of this union type.
* @return The alternate types of this union type. The returned set is
* immutable.
*/
public Iterable<JSType> getAlternates() {
return alternates;
}
@Override
public void forgiveUnknownNames() {
for (JSType type : getAlternates()) {
type.forgiveUnknownNames();
}
}
/**
* This predicate is used to test whether a given type can appear in a
* numeric context, such as an operand of a multiply operator.
*
* @return true if the type can appear in a numeric context.
*/
@Override
public boolean matchesNumberContext() {
// TODO(user): Reverse this logic to make it correct instead of generous.
for (JSType t : alternates) {
if (t.matchesNumberContext()) {
return true;
}
}
return false;
}
/**
* This predicate is used to test whether a given type can appear in a
* {@code String} context, such as an operand of a string concat ({@code +})
* operator.<p>
*
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>JSType that) {
boolean canAssign = true;
for (JSType t : alternates) {
if (t.isUnknownType()) {
return true;
}
canAssign &= t.canAssignTo(that);
}
return canAssign;
}
@Override
public boolean canBeCalled() {
for (JSType t : alternates) {
if (!t.canBeCalled()) {
return false;
}
}
return true;
}
@Override
public JSType restrictByNotNullOrUndefined() {
UnionTypeBuilder restricted = new UnionTypeBuilder(registry);
for (JSType t : alternates) {
restricted.addAlternate(t.restrictByNotNullOrUndefined());
}
return restricted.build();
}
@Override
public TernaryValue testForEquality(JSType that) {
TernaryValue result = null;
for (JSType t : alternates) {
TernaryValue test = t.testForEquality(that);
if (result == null) {
result = test;
} else if (!result.equals(test)) {
return UNKNOWN;
}
}
return result;
}
/**
* This predicate determines whether objects of this type can have the
* {@code null} value, and therefore can appear in contexts where
* {@code null} is expected.
*
* @return {@code true} for everything but {@code Number} and
* {@code Boolean} types.
*/
@Override
public boolean isNullable() {
for (JSType t : alternates) {
if (t.isNullable()) {
return true;
}
}
return false;
}
@Override
public boolean isUnknownType() {
for (JSType t : alternates) {
if (t.isUnknownType()) {
return true;
}
}
return false;
}
@Override
public JSType getLeastSupertype(JSType that) {
if (!that.isUnknownType()) {
for (JSType alternate : alternates) {
if (!alternate.isUnknownType() && that.isSubtype(alternate)) {
return this;
}
}
}
return getLeastSupertype(this, that);
}
JSType meet(JSType that) {
UnionTypeBuilder builder
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS> = new UnionTypeBuilder(registry);
for (JSType alternate : alternates) {
if (alternate.isSubtype(that)) {
builder.addAlternate(alternate);
}
}
if (that instanceof UnionType) {
for (JSType otherAlternate : ((UnionType) that).alternates) {
if (otherAlternate.isSubtype(this)) {
builder.addAlternate(otherAlternate);
}
}
} else if (that.isSubtype(this)) {
builder.addAlternate(that);
}
JSType result = builder.build();
if (!result.isNoType()) {
return result;
} else if (this.isObject() && that.isObject()) {
return getNativeType(JSTypeNative.NO_OBJECT_TYPE);
} else {
return getNativeType(JSTypeNative.NO_TYPE);
}
}
/**
* Two union types are equal if they have the same number of alternates
* and all alternates are equal.
*/
@Override
public boolean equals(Object object) {
if (object instanceof UnionType) {
UnionType that = (UnionType) object;
return alternates.equals(that.alternates);
} else {
return false;
}
}
@Override
public int hashCode() {
return this.hashcode;
}
@Override
public boolean isUnionType() {
return true;
}
@Override
public boolean isObject() {
for (JSType alternate : alternates) {
if (!alternate.isObject()) {
return false;
}
}
return true;
}
/**
* A {@link UnionType} contains a given type (alternate) iff the member
* vector contains it. Since the {@link #equals} method above conforms to
* the necessary semantics for the collection, everything works out just
* fine.
*
* @param alternate The alternate which might be in this union.
*
* @return {@code true} if the alternate is in the union
*/
public boolean contains(JSType alternate) {
return alternates.contains(alternate);
}
/**
* Returns a more restricted union type than {@code this} one, in which all
* subtypes of {@code type} have been removed.<p>
*
* Examples:
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>
* <ul>
* <li>{@code (number,string)} restricted by {@code number} is
* {@code string}</li>
* <li>{@code (null, EvalError, URIError)} restricted by
* {@code Error} is {@code null}</li>
* </ul>
*
* @param type the supertype of the types to remove from this union type
*/
public JSType getRestrictedUnion(JSType type) {
UnionTypeBuilder restricted = new UnionTypeBuilder(registry);
for (JSType t : alternates) {
if (t.isUnknownType() || !t.isSubtype(type)) {
restricted.addAlternate(t);
}
}
return restricted.build();
}
@Override public String toString() {
StringBuilder result = new StringBuilder();
boolean firstAlternate = true;
result.append("(");
SortedSet<JSType> sorted = new TreeSet<JSType>(ALPHA);
sorted.addAll(alternates);
for (JSType t : sorted) {
if (!firstAlternate) {
result.append("|");
}
result.append(t.toString());
firstAlternate = false;
}
result.append(")");
return result.toString();
}
@Override
public boolean isSubtype(JSType that) {
for (JSType element : alternates) {
if (!element.isSubtype(that)) {
return false;
}
}
return true;
}
@Override
public JSType getRestrictedTypeGivenToBooleanOutcome(boolean outcome) {
// gather elements after restriction
UnionTypeBuilder restricted = new UnionTypeBuilder(registry);
for (JSType element : alternates) {
restricted.addAlternate(
element.getRestrictedTypeGivenToBooleanOutcome(outcome));
}
return restricted.build();
}
@Override
public BooleanLiteralSet getPossibleToBooleanOutcomes() {
BooleanLiteralSet literals = BooleanLiteralSet.EMPTY;
for (JSType element : alternates) {
literals = literals.union(element.getPossibleToBooleanOutcomes());
if (literals == BooleanLiteralSet.BOTH) {
break;
}
}
return literals;
}
@Override
public TypePair getTypesUnderEquality(JSType that) {
UnionTypeBuilder thisRestricted = new
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS> UnionTypeBuilder(registry);
UnionTypeBuilder thatRestricted = new UnionTypeBuilder(registry);
for (JSType element : alternates) {
TypePair p = element.getTypesUnderEquality(that);
if (p.typeA != null) {
thisRestricted.addAlternate(p.typeA);
}
if (p.typeB != null) {
thatRestricted.addAlternate(p.typeB);
}
}
return new TypePair(
thisRestricted.build(),
thatRestricted.build());
}
@Override
public TypePair getTypesUnderInequality(JSType that) {
UnionTypeBuilder thisRestricted = new UnionTypeBuilder(registry);
UnionTypeBuilder thatRestricted = new UnionTypeBuilder(registry);
for (JSType element : alternates) {
TypePair p = element.getTypesUnderInequality(that);
if (p.typeA != null) {
thisRestricted.addAlternate(p.typeA);
}
if (p.typeB != null) {
thatRestricted.addAlternate(p.typeB);
}
}
return new TypePair(
thisRestricted.build(),
thatRestricted.build());
}
@Override
public TypePair getTypesUnderShallowInequality(JSType that) {
UnionTypeBuilder thisRestricted = new UnionTypeBuilder(registry);
UnionTypeBuilder thatRestricted = new UnionTypeBuilder(registry);
for (JSType element : alternates) {
TypePair p = element.getTypesUnderShallowInequality(that);
if (p.typeA != null) {
thisRestricted.addAlternate(p.typeA);
}
if (p.typeB != null) {
thatRestricted.addAlternate(p.typeB);
}
}
return new TypePair(
thisRestricted.build(),
thatRestricted.build());
}
@Override
public <T> T visit(Visitor<T> visitor) {
return visitor.caseUnionType(this);
}
@Override
JSType resolveInternal(ErrorReporter t, StaticScope<JSType> scope) {
setResolvedTypeInternal(this); // for circularly defined types.
boolean changed = false;
ImmutableSet.Builder<JSType> resolvedTypes = ImmutableSet.builder();
for (JSType alternate : alternates)
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS> {
JSType newAlternate = alternate.resolve(t, scope);
changed |= (alternate != newAlternate);
resolvedTypes.add(alternate);
}
if (changed) {
Set<JSType> newAlternates = resolvedTypes.build();
Preconditions.checkState(newAlternates.hashCode() == this.hashcode);
alternates = newAlternates;
}
return this;
}
}
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS> } else {
return getNativeType(JSTypeNative.NO_TYPE);
}
}
public JSType caseAllType() {
return getNativeType(JSTypeNative.NO_OBJECT_TYPE);
}
public JSType caseVoidType() {
return getNativeType(JSTypeNative.NO_OBJECT_TYPE);
}
public JSType caseEnumElementType(EnumElementType type) {
return type.getPrimitiveType().visit(this);
}
}
NoObjectType(JSTypeRegistry registry) {
super(registry, null, null, null, null, null, null, true, true);
}
@Override
public JSType getReturnType() {
return this;
}
@Override
public ObjectType getInstanceType() {
return this;
}
@Override
public TernaryValue testForEquality(JSType that) {
return that.isEmptyType() ? TernaryValue.TRUE : TernaryValue.UNKNOWN;
}
@Override
public boolean isSubtype(JSType that) {
if (JSType.isSubtype(this, that)) {
return true;
} else {
return that.isObject() && !that.isNoType();
}
}
@Override
public boolean isFunctionType() {
return false;
}
@Override
public boolean isNoObjectType() {
return true;
}
@Override
public JSType getLeastSupertype(JSType that) {
return that.visit(leastSupertypeVisitor);
}
@Override
public JSType getGreatestSubtype(JSType that) {
return that.visit(greatestSubtypeVisitor);
}
@Override
public ObjectType getImplicitPrototype() {
return null;
}
@Override
public String getReferenceName() {
return null;
}
@Override
public boolean matchesNumberContext() {
return true;
}
@Override
public boolean matchesObjectContext() {
return true;
}
@Override
public boolean matchesStringContext() {
return true;
}
@Override
public boolean equals(Object that) {
return this == that;
}
@Override
public int hashCode() {
return System.identityHashCode(this);
}
@Override
public int getPropertiesCount() {
// Should never be called, returning the biggest number to highlight the
// '
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>";
if (d == Double.NEGATIVE_INFINITY)
return "-Infinity";
if (d == 0.0)
return "0";
if ((base < 2) || (base > 36)) {
throw Context.reportRuntimeError1(
"msg.bad.radix", Integer.toString(base));
}
if (base != 10) {
return DToA.JS_dtobasestr(base, d);
} else {
StringBuffer result = new StringBuffer();
DToA.JS_dtostr(result, DToA.DTOSTR_STANDARD, 0, d);
return result.toString();
}
}
/**
* If str is a decimal presentation of Uint32 value, return it as long.
* Othewise return -1L;
*/
public static long testUint32String(String str)
{
// The length of the decimal string representation of
// UINT32_MAX_VALUE, 4294967296
final int MAX_VALUE_LENGTH = 10;
int len = str.length();
if (1 <= len && len <= MAX_VALUE_LENGTH) {
int c = str.charAt(0);
c -= '0';
if (c == 0) {
// Note that 00,01 etc. are not valid Uint32 presentations
return (len == 1) ? 0L : -1L;
}
if (1 <= c && c <= 9) {
long v = c;
for (int i = 1; i != len; ++i) {
c = str.charAt(i) - '0';
if (!(0 <= c && c <= 9)) {
return -1;
}
v = 10 * v + c;
}
// Check for overflow
if ((v >>> 32) == 0) {
return v;
}
}
}
return -1;
}
static boolean isSpecialProperty(String s)
{
return s.equals("__proto__") || s.equals("__parent__");
}
// ------------------
// Statements
// ------------------
public static String getMessage0(String messageId)
{
return getMessage(messageId, null);
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS> Object messageHelper)
{
// XXX Use value for better error reporting
String msg = (messageHelper == null)
? "null" : messageHelper.toString();
return typeError2("msg.isnt.function", msg,
value == null ? "null" : value.getClass().getName());
}
static int lastIndexResult(Context cx)
{
return cx.scratchIndex;
}
public static void storeUint32Result(Context cx, long value)
{
if ((value >>> 32) != 0)
throw new IllegalArgumentException();
cx.scratchUint32 = value;
}
public static long lastUint32Result(Context cx)
{
long value = cx.scratchUint32;
if ((value >>> 32) != 0)
throw new IllegalStateException();
return value;
}
static String makeUrlForGeneratedScript
(boolean isEval, String masterScriptUrl, int masterScriptLine)
{
if (isEval) {
return masterScriptUrl+'#'+masterScriptLine+"(eval)";
} else {
return masterScriptUrl+'#'+masterScriptLine+"(Function)";
}
}
static boolean isGeneratedScript(String sourceUrl) {
// ALERT: this may clash with a valid URL containing (eval) or
// (Function)
return sourceUrl.indexOf("(eval)") >= 0
|| sourceUrl.indexOf("(Function)") >= 0;
}
public static final Object[] emptyArgs = new Object[0];
public static final String[] emptyStrings = new String[0];
}
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>/*
*
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Rhino code, released
* May 6, 1999.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1997-1999
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Bob Jervis
* Google Inc.
*
* Alternatively, the contents of this file may be used under the terms of
* the GNU General Public License Version 2 or later (the "GPL"), in which
* case the provisions of the GPL are applicable instead of those above. If
* you wish to allow use of your version of this file only under the terms of
* the GPL and not to allow others to use your version of this file under the
* MPL, indicate your decision by deleting the provisions above and replacing
* them with the notice and other provisions required by the GPL. If you do
* not delete the provisions above, a recipient may use your version of this
* file under either the MPL or the GPL.
*
* ***** END LICENSE BLOCK ***** */
package com.google.javascript.rhino.jstype;
/**
* The {@code StaticSlot} interface must be implemented by variables that can
* appear as members of a {@code StaticScope}.
*
*
*
* @param <T> The type of information stored about the slot
*/
public interface StaticSlot<T> {
/**
* Gets the name of the slot.
*/
String getName();
/**
* Returns the type information, if any,
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>Call(Node callNode) {
return null;
}
@Override
public boolean isSuperClassReference(String propertyName) {
return false;
}
@Override
public String extractClassNameIfProvide(Node node, Node parent) {
String message = "only implemented in GoogleCodingConvention";
throw new UnsupportedOperationException(message);
}
@Override
public String extractClassNameIfRequire(Node node, Node parent) {
String message = "only implemented in GoogleCodingConvention";
throw new UnsupportedOperationException(message);
}
@Override
public String getExportPropertyFunction() {
return null;
}
@Override
public String getExportSymbolFunction() {
return null;
}
@Override
public List<String> identifyTypeDeclarationCall(Node n) {
return null;
}
@Override
public String identifyTypeDefAssign(Node n) {
return null;
}
@Override
public void applySubclassRelationship(FunctionType parentCtor,
FunctionType childCtor, SubclassType type) {
// do nothing
}
@Override
public String getAbstractMethodName() {
return null;
}
@Override
public String getSingletonGetterClassName(Node callNode) {
return null;
}
@Override
public void applySingletonGetter(FunctionType functionType,
FunctionType getterType, ObjectType objectType) {
// do nothing.
}
@Override
public DelegateRelationship getDelegateRelationship(Node callNode) {
return null;
}
@Override
public void applyDelegateRelationship(
ObjectType delegateSuperclass, ObjectType delegateBase,
ObjectType delegator, FunctionType delegateProxy,
FunctionType findDelegate) {
// do nothing.
}
@Override
public String getDelegateSuperclassName() {
return null;
}
@Override
public void defineDelegateProxyProperties(
JSTypeRegistry registry, Scope scope,
Map<ObjectType, ObjectType> delegateProxyMap) {
// do nothing.
}
@Override
public String getGlobalObject() {
return "window";
}
@Override
public boolean isPropertyTestFunction(Node call) {
return false;
}
@Override
public ObjectLiteralCast getObjectLiteralCast(NodeTraversal t,
Node callNode) {
return null;
}
}
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS> fileName,
Generator generator) {
return new JSSourceFile(SourceFile.fromGenerator(fileName, generator));
}
private SourceFile referenced;
private JSSourceFile(SourceFile referenced) {
super(referenced.getName());
this.referenced = referenced;
}
@Override
public String getCode() throws IOException {
return referenced.getCode();
}
@Override
public void clearCachedSource() {
referenced.clearCachedSource();
}
@Override
@VisibleForTesting
String getCodeNoCache() {
return referenced.getCodeNoCache();
}
}
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>/*
* Copyright 2007 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.collect.ImmutableSet;
import com.google.javascript.jscomp.CheckLevel;
import java.util.Set;
/**
* Abstract message formatter providing default behavior for implementations
* of {@link MessageFormatter} needing a {@link SourceExcerptProvider}.
*
*
*/
public abstract class AbstractMessageFormatter implements MessageFormatter {
private final SourceExcerptProvider source;
private boolean colorize;
public AbstractMessageFormatter(SourceExcerptProvider source) {
this.source = source;
}
public void setColorize(boolean colorize) {
this.colorize = colorize;
}
/**
* Get the source excerpt provider.
*/
protected final SourceExcerptProvider getSource() {
return source;
}
private static final Set<String> SUPPORTED_COLOR_TERMINALS =
ImmutableSet.of("xterm",
"xterm-color",
"xterm-256color",
"screen-bce");
static boolean termSupportsColor(String term) {
return SUPPORTED_COLOR_TERMINALS.contains(term);
}
private static enum Color {
ERROR("\033[31m"),
WARNING("\033[35m"),
RESET("\033[39m");
private final String controlCharacter;
Color(String controlCharacter) {
this.controlCharacter = controlCharacter;
}
public String getControlCharacter() {
return controlCharacter;
}
}
String getLevelName(CheckLevel level) {
switch (level) {
case ERROR: return maybeColor
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>/*
* Copyright 2009 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import com.google.javascript.jscomp.NodeTraversal.AbstractShallowCallback;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import java.io.IOException;
import java.util.List;
import java.util.Set;
/**
* A class for the internal representation of an input to the compiler.
* Wraps a {@link SourceAst} and maintain state such as module for the input and
* whether the input is an extern. Also calculates provided and required types.
*
*
*/
public class CompilerInput implements SourceAst {
private static final long serialVersionUID = 1L;
// Info about where the file lives.
private JSModule module;
private final boolean isExtern;
final private String name;
// The AST.
private final SourceAst ast;
// Provided and required symbols.
private final Set<String> provides = Sets.newHashSet();
private final Set<String> requires = Sets.newHashSet();
public CompilerInput(SourceAst ast) {
this(ast, ast.getSourceFile().getName(), false);
}
public CompilerInput(SourceAst ast, boolean isExtern) {
this(ast, ast.getSourceFile().getName(), isExtern);
}
public CompilerInput(SourceAst ast, String inputName, boolean isExtern) {
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>
this.ast = ast;
this.name = inputName;
this.isExtern = isExtern;
}
public CompilerInput(JSSourceFile file) {
this(file, false);
}
public CompilerInput(JSSourceFile file, boolean isExtern) {
this.ast = new JsAst(file);
this.name = file.getName();
this.isExtern = isExtern;
}
/** Returns a name for this input. Must be unique across all inputs. */
public String getName() {
return name;
}
@Override
public Node getAstRoot(AbstractCompiler compiler) {
return ast.getAstRoot(compiler);
}
@Override
public void clearAst() {
ast.clearAst();
}
@Override
public SourceFile getSourceFile() {
return ast.getSourceFile();
}
@Override
public void setSourceFile(SourceFile file) {
ast.setSourceFile(file);
}
/** Returns the SourceAst object on which this input is based. */
public SourceAst getSourceAst() {
return ast;
}
/** Gets a list of types depended on by this input. */
public Set<String> getRequires(AbstractCompiler compiler) {
if (getAstRoot(compiler) != null) {
DepsFinder deps = new DepsFinder(compiler, true);
NodeTraversal.traverse(compiler, getAstRoot(compiler), deps);
requires.addAll(deps.types);
return requires;
} else {
return ImmutableSet.<String>of();
}
}
/** Gets a list of types provided by this input. */
public Set<String> getProvides(AbstractCompiler compiler) {
if (getAstRoot(compiler) != null) {
DepsFinder deps = new DepsFinder(compiler, false);
NodeTraversal.traverse(compiler, getAstRoot(compiler), deps);
provides.addAll(deps.types);
return provides;
} else {
return ImmutableSet.<String>of();
}
}
private class DepsFinder extends AbstractShallowCallback {
private boolean findRequire;
private List<String> types;
private CodingConvention codingConvention;
DepsFinder(AbstractCompiler compiler, boolean findRequire) {
this.findRequire = findRequire;
this.
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>codingConvention = compiler.getCodingConvention();
this.types = Lists.newArrayList();
}
public void visit(NodeTraversal t, Node n, Node parent) {
switch (n.getType()) {
case Token.CALL:
String className = findRequire
? codingConvention.extractClassNameIfRequire(n, parent)
: codingConvention.extractClassNameIfProvide(n, parent);
if (className != null) {
types.add(className);
}
break;
}
}
}
/**
* Gets the source line for the indicated line number.
*
* @param lineNumber the line number, 1 being the first line of the file.
* @return The line indicated. Does not include the newline at the end
* of the file. Returns {@code null} if it does not exist,
* or if there was an IO exception.
*/
public String getLine(int lineNumber) {
return getSourceFile().getLine(lineNumber);
}
/**
* Get a region around the indicated line number. The exact definition of a
* region is implementation specific, but it must contain the line indicated
* by the line number. A region must not start or end by a carriage return.
*
* @param lineNumber the line number, 1 being the first line of the file.
* @return The line indicated. Returns {@code null} if it does not exist,
* or if there was an IO exception.
*/
public Region getRegion(int lineNumber) {
return getSourceFile().getRegion(lineNumber);
}
public String getCode() throws IOException {
return getSourceFile().getCode();
}
/** Returns the module to which the input belongs. */
public JSModule getModule() {
return module;
}
/** Sets the module to which the input belongs. */
public void setModule(JSModule module) {
// An input may only belong to one module.
Preconditions.checkArgument(
module == null || this.module == null || this.module == module);
this.module = module;
}
public boolean isExtern() {
return isExtern;
}
}
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>}
*/
public String format(CheckLevel level, MessageFormatter formatter) {
switch (level) {
case ERROR:
return formatter.formatError(this);
case WARNING:
return formatter.formatWarning(this);
default:
return null;
}
}
@Override
public String toString() {
// TODO(user): remove custom toString.
return type.key + ". " + description + " at " +
(sourceName != null && sourceName.length() > 0 ?
sourceName : "(unknown source)") + " line " +
(lineNumber != -1 ? String.valueOf(lineNumber) : "(unknown line)");
}
/**
* Get the character number.
*/
public int getCharno() {
return charno;
}
@Override
public boolean equals(Object o) {
// Generated by Intellij IDEA
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
JSError jsError = (JSError) o;
if (charno != jsError.charno) {
return false;
}
if (lineNumber != jsError.lineNumber) {
return false;
}
if (!description.equals(jsError.description)) {
return false;
}
if (level != jsError.level) {
return false;
}
if (sourceName != null ? !sourceName.equals(jsError.sourceName)
: jsError.sourceName != null) {
return false;
}
if (!type.equals(jsError.type)) {
return false;
}
return true;
}
@Override
public int hashCode() {
// Generated by Intellij IDEA
int result = type.hashCode();
result = 31 * result + description.hashCode();
result = 31 * result + (sourceName != null ? sourceName.hashCode() : 0);
result = 31 * result + lineNumber;
result = 31 * result + level.hashCode();
result = 31 * result + charno;
return result;
}
}
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>ThreadTrace()} to enable the
* Tracer logging, otherwise Tracer does nothing. The requirement to call
* {@code initCurrentThreadTrace} avoids the situtation where Tracer is called
* without the explicit knowledge of the application authors because they
* happen to use a class in another package that uses Tracer. If {@link
* Tracer#logCurrentThreadTrace} is called without calling {@link
* Tracer#initCurrentThreadTrace()}, then a Third Eye WARNING message is logged,
* which should help track down the problem.
*
*
*/
final class Tracer {
// package-private for access from unit tests
static final Logger logger =
Logger.getLogger(Tracer.class.getName());
/**
* Whether pretty printing is enabled. This is intended to be set once
* at application startup.
*/
private static volatile boolean defaultPrettyPrint;
/* This list is guaranteed to only increase in length. It contains a list of additional
* statistics that the user wants to keep track of.
*/
private static List<TracingStatistic> extraTracingStatistics =
new CopyOnWriteArrayList<TracingStatistic>();
/** Values returned by extraTracingStatistics */
private long[] extraTracingValues;
/** The type for grouping traces, may be null */
private final @Nullable String type;
/** A comment string for the report */
private final String comment;
/** Start time of the trace */
private final long startTimeMs;
/** Stop time of the trace, non-final */
private long stopTimeMs;
/**
* Record our starter thread in order to trap Traces that are started in one
* thread and stopped in another
*/
final Thread startThread;
/**
* We limit the number of events in a Trace in order to catch memory
* leaks (a thread that keeps logging events and never clears them).
* This number is arbitrary and can be increased if necessary (though
* if there are more than 1000 events then the Tracer is probably being
* misused).
*/
static final int MAX_TRACE_SIZE = 1000;
/**
* For unit testing. Can't use {@link com.google.common.time} because
* this code is in base and has minimal dependencies.
*/
static interface InternalClock {
long currentTimeMillis();
}
/**
*
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS> Construct a tracer whose type is based on the short name of the object
* @param object Object to use as type name
* @param comment A comment
* @return new Tracer.
*/
static Tracer shortName(Object object, String comment) {
if (object == null) {
return new Tracer(comment);
}
return new Tracer(object.getClass().getSimpleName(), comment);
}
/**
* Converts 'v' to a string and pads it with up to 16 spaces for
* improved alignment.
* @param v The value to convert.
* @param digits_column_width The desired with of the string.
*/
private static String longToPaddedString(long v, int digits_column_width) {
int digit_width = numDigits(v);
StringBuilder sb = new StringBuilder();
appendSpaces(sb, digits_column_width - digit_width);
sb.append(v);
return sb.toString();
}
/**
* Gets the number of digits in an integer when printed in base 10. Assumes
* a positive integer.
* @param n The value.
* @return The number of digits in the string.
*/
private static int numDigits(long n) {
int i = 0;
do {
i++;
n = n / 10;
} while (n > 0);
return i;
}
/**
* Gets a string of spaces of the length specified.
* @param sb The string builder to append to.
* @param numSpaces The number of spaces in the string.
*/
@VisibleForTesting
static void appendSpaces(StringBuilder sb, int numSpaces) {
if (numSpaces > 16) {
logger.warning("Tracer.appendSpaces called with large numSpaces");
// Avoid long loop in case some bug in the caller
numSpaces = 16;
}
while (numSpaces >= 5) {
sb.append(" ");
numSpaces -= 5;
}
// We know it's less than 5 now
switch (numSpaces) {
case 1:
sb.append(" ");
break;
case 2:
sb.append(" ");
break;
case 3:
sb.append("
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS> ");
break;
case 4:
sb.append(" ");
break;
}
}
/**
* Adds a new tracing statistic to a trace
*
* @param tracingStatistic to enable a run
* @return The index of this statistic (for use with stat.extraInfo()), or
* -1 if the statistic is not enabled.
*/
static int addTracingStatistic(TracingStatistic tracingStatistic) {
// Check to see if we can enable the tracing statistic before actually
// adding it.
if (tracingStatistic.enable()) {
// No synchronization needed, since this is a copy-on-write array.
extraTracingStatistics.add(tracingStatistic);
// 99.9% of the time, this will be O(1) and return extraTracingStatistics.length - 1
return extraTracingStatistics.lastIndexOf(tracingStatistic);
} else {
return -1;
}
}
/**
* For testing purposes only. These removes all current tracers. Severe errors can occur
* if there are any active tracers going on when this is called.
*
* The test suite uses this to remove any tracers that it has added.
*/
@VisibleForTesting
static void clearTracingStatisticsTestingOnly() {
extraTracingStatistics.clear();
}
/**
* Stop the trace.
* This may only be done once and must be done from the same thread
* that started it.
* @param silence_threshold Traces for time less than silence_threshold
* ms will be left out of the trace report. A value of -1 indicates
* that the current ThreadTrace silence_threshold should be used.
* @return The time that this trace actually ran
*/
long stop(int silence_threshold) {
Preconditions.checkState(Thread.currentThread() == startThread);
ThreadTrace trace = getThreadTrace();
// Do nothing if the thread trace was not initialized.
if (!trace.isInitialized()) {
return 0;
}
stopTimeMs = clock.currentTimeMillis();
if (extraTracingValues != null) {
// We use extraTracingValues.length rather than extraTracingStatistics.size() because
// a new statistic may have been added
for (int i = 0; i < extraTracingValues.length; i++) {
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>Statistics.get(i).getUnits());
sb.append("; ");
}
}
}
sb.append(indent);
sb.append(tracer.toString());
return sb.toString();
}
}
/** Stores a thread's Trace */
static final class ThreadTrace {
/** Events taking less than this number of milliseconds are not reported. */
int defaultSilenceThreshold; // non-final
/** The Events corresponding to each startEvent/stopEvent */
final ArrayList<Event> events = new ArrayList<Event>();
/** Tracers that have not had their .stop() called */
final HashSet<Tracer> outstandingEvents = new HashSet<Tracer>();
/** Map from type to Stat object */
final Map<String, Stat> stats = new HashMap<String, Stat>();
/**
* True if {@code outstandingEvents} has been cleared because we exceeded
* the max trace limit.
*/
boolean isOutstandingEventsTruncated = false;
/**
* True if {@code events} has been cleared because we exceeded the max
* trace limit.
*/
boolean isEventsTruncated = false;
/**
* Set to true if {@link Tracer#initCurrentThreadTrace()} was called by
* the current thread.
*/
boolean isInitialized = false;
/**
* Whether pretty printing is enabled for the trace.
*/
boolean prettyPrint = false;
/** Initialize the trace. */
void init() {
isInitialized = true;
}
/** Is initialized? */
boolean isInitialized() {
return isInitialized;
}
/**
* Called by the constructor {@link Tracer#Tracer(String, String)} to create
* a start event.
*/
void startEvent(Tracer t) {
events.add(new Event(true, t));
boolean notAlreadyOutstanding = outstandingEvents.add(t);
Preconditions.checkState(notAlreadyOutstanding);
}
/**
* Called by {@link Tracer#stop()} to create a stop event.
*/
void endEvent(Tracer t, int silenceThreshold) {
boolean wasOutstanding = outstandingEvents.remove(t);
if (!wasOutstanding) {
if (isOutstandingEventsTruncated) {
// The events stack overflowed and was truncated, so just log a
// warning. Otherwise, we get an exception which is extremely
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS> // confusing.
logger.log(Level.WARNING,
"event not found, probably because the event stack "
+ "overflowed and was truncated",
new Throwable());
} else {
// throw an exception if the event was not found and the events stack
// is pristine
throw new IllegalStateException();
}
}
long elapsed = t.stopTimeMs - t.startTimeMs;
if (silenceThreshold == -1) { // use default
silenceThreshold = defaultSilenceThreshold;
}
if (elapsed < silenceThreshold) {
// If this one is silent then we need to remove the start Event
boolean removed = false;
for (int i = 0; i < events.size(); i++) {
Event e = events.get(i);
if (e.tracer == t) {
Preconditions.checkState(e.isStart);
events.remove(i);
removed = true;
break;
}
}
// Only assert if we didn't find the original and the events
// weren't truncated.
Preconditions.checkState(removed || isEventsTruncated);
} else {
events.add(new Event(false, t));
}
if (t.type != null) {
Stat stat = stats.get(t.type);
if (stat == null) {
stat = new Stat();
if (!extraTracingStatistics.isEmpty()) {
stat.extraInfo = new int[extraTracingStatistics.size()];
}
stats.put(t.type, stat);
}
stat.count++;
if (typeToCountMap != null) {
typeToCountMap.incrementBy(t.type, 1);
}
stat.clockTime += elapsed;
if (typeToTimeMap != null) {
typeToTimeMap.incrementBy(t.type, elapsed);
}
if (stat.extraInfo != null && t.extraTracingValues != null) {
int overlapLength = Math.min(stat.extraInfo.length, t.extraTracingValues.length);
for (int i = 0; i < overlapLength; i++) {
stat.extraInfo[i] += t.extraTracingValues[i];
AtomicTracerStatMap map = extraTracingStatistics.get(i).getTracingStat();
if (map !=
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS> null) {
map.incrementBy(t.type, t.extraTracingValues[i]);
}
}
}
if (elapsed < silenceThreshold) {
stat.silent++;
if (typeToSilentMap != null) {
typeToSilentMap.incrementBy(t.type, 1);
}
}
}
}
boolean isEmpty() {
return events.size() == 0 && outstandingEvents.size() == 0;
}
void truncateOutstandingEvents() {
isOutstandingEventsTruncated = true;
outstandingEvents.clear();
}
void truncateEvents() {
isEventsTruncated = true;
events.clear();
}
/** Produces the lovely Trace seen in the class comments */
// Nullness checker does not understand that prettyPrint => indent != null
@SuppressWarnings("nullness")
@Override public String toString() {
int numDigits = getMaxDigits();
StringBuilder sb = new StringBuilder();
long etime = -1;
LinkedList<String> indent = prettyPrint ? new LinkedList<String>() : null;
for (Event e : events) {
if (prettyPrint && !e.isStart && !indent.isEmpty()) {
indent.pop();
}
sb.append(" ");
if (prettyPrint) {
sb.append(e.toString(etime, Joiner.on("").join(indent), numDigits));
} else {
sb.append(e.toString(etime, "", 4));
}
etime = e.eventTime();
sb.append('\n');
if (prettyPrint && e.isStart) {
indent.push("| ");
}
}
if (outstandingEvents.size() != 0) {
long now = clock.currentTimeMillis();
sb.append(" Unstopped timers:\n");
for (Tracer t : outstandingEvents) {
sb.append(" ").
append(t).
append(" (").
append(now - t.startTimeMs).
append(" ms, started at ").
append(formatTime(t.startTimeMs)).
append(")\n");
}
}
for (String key : stats.keySet()) {
Stat stat = stats.get(key);
if (stat.count > 1) {
sb.append(" TOTAL ").
append(
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS> path through
// the code identical to how it's been for years.
this.outputCharsetEncoder = null;
} else {
this.outputCharsetEncoder = outputCharset.newEncoder();
}
}
CodeGenerator(CodeConsumer consumer, Charset outputCharset) {
this(consumer, outputCharset, true);
}
CodeGenerator(CodeConsumer consumer) {
this(consumer, null, false);
}
void add(String str) {
cc.add(str);
}
private void addIdentifier(String identifier) {
cc.addIdentifier(identifierEscape(identifier));
}
void add(Node n) {
add(n, Context.OTHER);
}
void add(Node n, Context context) {
if (!cc.continueProcessing()) {
return;
}
int type = n.getType();
String opstr = NodeUtil.opToStr(type);
int childCount = n.getChildCount();
Node first = n.getFirstChild();
Node last = n.getLastChild();
// Handle all binary operators
if (opstr != null && first != last) {
Preconditions.checkState(childCount == 2);
int p = NodeUtil.precedence(type);
addLeftExpr(first, p, context);
cc.addOp(opstr, true);
// For right-hand-side of operations, only pass context if it's
// the IN_FOR_INIT_CLAUSE one.
Context rhsContext = getContextForNoInOperator(context);
// Handle associativity.
// e.g. if the parse tree is a * (b * c),
// we can simply generate a * b * c.
if (last.getType() == type &&
NodeUtil.isAssociative(type)) {
addExpr(last, p, rhsContext);
} else if (NodeUtil.isAssignmentOp(n) && NodeUtil.isAssignmentOp(last)) {
// Assignments are the only right-associative binary operators
addExpr(last, p, rhsContext);
} else {
addExpr(last, p + 1, rhsContext);
}
return;
}
cc.startSourceMapping(n);
switch (type) {
case Token.TRY: {
Preconditions.checkState(first.getNext().getType() ==
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS> Token.BLOCK &&
first.getNext().getChildCount() <= 1);
Preconditions.checkState(childCount >= 2 && childCount <= 3);
add("try");
add(first, Context.PRESERVE_BLOCK);
// second child contains the catch block, or nothing if there
// isn't a catch block
Node catchblock = first.getNext().getFirstChild();
if (catchblock != null) {
add(catchblock);
}
if (childCount == 3) {
add("finally");
add(last, Context.PRESERVE_BLOCK);
}
break;
}
case Token.CATCH:
Preconditions.checkState(childCount == 3);
if (first.getNext().getType() != Token.EMPTY) {
throw new Error("Catch conditions not suppored because I think" +
" that it may be a netscape only feature.");
}
add("catch(");
add(first);
add(")");
add(last, Context.PRESERVE_BLOCK);
break;
case Token.THROW:
Preconditions.checkState(childCount == 1);
add("throw");
add(first);
// Must have a ';' after a throw statement, otherwise safari can't
// parse this.
cc.endStatement(true);
break;
case Token.RETURN:
add("return");
if (childCount == 1) {
add(first);
} else {
Preconditions.checkState(childCount == 0);
}
cc.endStatement();
break;
case Token.VAR:
if (first != null) {
add("var ");
addList(first, false, getContextForNoInOperator(context));
}
break;
case Token.NAME:
if (first == null || first.getType() == Token.EMPTY) {
addIdentifier(n.getString());
} else {
Preconditions.checkState(childCount == 1);
addIdentifier(n.getString());
cc.addOp("=", true);
if (first.getType() == Token.COMMA) {
addExpr(first, NodeUtil.precedence(Token.ASSIGN));
} else {
// Add expression, consider nearby code at lowest level of
// precedence.
addExpr(first, 0, getContextForNoInOperator
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>(context));
}
}
break;
case Token.ARRAYLIT:
add("[");
addList(first, (int[]) n.getProp(Node.SKIP_INDEXES_PROP));
add("]");
break;
case Token.LP:
add("(");
addList(first);
add(")");
break;
case Token.COMMA:
addList(first, false, context);
break;
case Token.NUMBER:
Preconditions.checkState(childCount == 0);
cc.addNumber(n.getDouble());
break;
case Token.TYPEOF:
case Token.VOID:
case Token.NOT:
case Token.BITNOT:
case Token.POS:
case Token.NEG: {
// All of these unary operators are right-associative
Preconditions.checkState(childCount == 1);
cc.addOp(NodeUtil.opToStrNoFail(type), false);
addExpr(first, NodeUtil.precedence(type));
break;
}
case Token.HOOK: {
Preconditions.checkState(childCount == 3);
int p = NodeUtil.precedence(type);
addLeftExpr(first, p + 1, context);
cc.addOp("?", true);
addExpr(first.getNext(), p);
cc.addOp(":", true);
addExpr(last, p);
break;
}
case Token.REGEXP:
if (first.getType() != Token.STRING ||
last.getType() != Token.STRING) {
throw new Error("Expected children to be strings");
}
String regexp = regexpEscape(first.getString(), outputCharsetEncoder);
// I only use one .add because whitespace matters
if (childCount == 2) {
add(regexp + last.getString());
} else {
Preconditions.checkState(childCount == 1);
add(regexp);
}
break;
case Token.GET_REF:
add(first);
break;
case Token.REF_SPECIAL:
Preconditions.checkState(childCount == 1);
add(first);
add(".");
add((String) n.getProp(Node.NAME_PROP));
break;
case Token.FUNCTION:
Preconditions.checkState(childCount == 3);
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS> boolean funcNeedsParens = (context == Context.START_OF_EXPR);
if (funcNeedsParens) {
add("(");
}
add("function");
add(first);
add(first.getNext());
add(last, Context.PRESERVE_BLOCK);
cc.endFunction(context == Context.STATEMENT);
if (funcNeedsParens) {
add(")");
}
break;
case Token.SCRIPT:
case Token.BLOCK: {
boolean stripBlock = n.isSyntheticBlock() ||
((context != Context.PRESERVE_BLOCK) && (n.getChildCount() < 2));
if (!stripBlock) {
cc.beginBlock();
}
for (Node c = first; c != null; c = c.getNext()) {
add(c, Context.STATEMENT);
// VAR doesn't include ';' since it gets used in expressions
if (c.getType() == Token.VAR) {
cc.endStatement();
}
if (c.getType() == Token.FUNCTION) {
cc.maybeLineBreak();
}
// Prefer to break lines in between top-level statements
// because top level statements are more homogeneous.
if (type == Token.SCRIPT) {
cc.notePreferredLineBreak();
}
}
if (!stripBlock) {
cc.endBlock(context == Context.STATEMENT);
}
break;
}
case Token.FOR:
if (childCount == 4) {
add("for(");
if (first.getType() == Token.VAR) {
add(first, Context.IN_FOR_INIT_CLAUSE);
} else {
addExpr(first, 0, Context.IN_FOR_INIT_CLAUSE);
}
add(";");
add(first.getNext());
add(";");
add(first.getNext().getNext());
add(")");
addNonEmptyExpression(
last, getContextForNonEmptyExpression(context), false);
} else {
Preconditions.checkState(childCount == 3);
add("for(");
add(first);
add("in");
add(first.getNext());
add(")");
addNonEmptyExpression(
last, getContextForNonEmptyExpression(context), false);
}
break
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>;
case Token.DO:
Preconditions.checkState(childCount == 2);
add("do");
addNonEmptyExpression(first, Context.OTHER, false);
add("while(");
add(last);
add(")");
cc.endStatement();
break;
case Token.WHILE:
Preconditions.checkState(childCount == 2);
add("while(");
add(first);
add(")");
addNonEmptyExpression(
last, getContextForNonEmptyExpression(context), false);
break;
case Token.EMPTY:
Preconditions.checkState(childCount == 0);
break;
case Token.GETPROP: {
Preconditions.checkState(childCount == 2);
Preconditions.checkState(last.getType() == Token.STRING);
boolean needsParens = (first.getType() == Token.NUMBER);
if (needsParens) {
add("(");
}
addLeftExpr(first, NodeUtil.precedence(type), context);
if (needsParens) {
add(")");
}
add(".");
addIdentifier(last.getString());
break;
}
case Token.GETELEM:
Preconditions.checkState(childCount == 2);
addLeftExpr(first, NodeUtil.precedence(type), context);
add("[");
add(first.getNext());
add("]");
break;
case Token.WITH:
Preconditions.checkState(childCount == 2);
add("with(");
add(first);
add(")");
addNonEmptyExpression(
last, getContextForNonEmptyExpression(context), false);
break;
case Token.INC:
case Token.DEC: {
Preconditions.checkState(childCount == 1);
String o = type == Token.INC ? "++" : "--";
int postProp = n.getIntProp(Node.INCRDECR_PROP, 0);
// A non-zero post-prop value indicates a post inc/dec, default of zero
// is a pre-inc/dec.
if (postProp != 0) {
addLeftExpr(first, NodeUtil.precedence(type), context);
cc.addOp(o, false);
} else {
cc.addOp(o, false);
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>
add(first);
}
break;
}
case Token.CALL:
// If the left hand side of the call is a direct reference to eval,
// then it must have a DIRECT_EVAL annotation. If it does not, then
// that means it was originally an indirect call to eval, and that
// indirectness must be preserved.
if (first.getType() == Token.NAME &&
"eval".equals(first.getString()) &&
!first.getBooleanProp(Node.DIRECT_EVAL)) {
add("(0,eval)");
} else {
addLeftExpr(first, NodeUtil.precedence(type), context);
}
add("(");
addList(first.getNext());
add(")");
break;
case Token.IF:
boolean hasElse = childCount == 3;
boolean ambiguousElseClause =
context == Context.BEFORE_DANGLING_ELSE && !hasElse;
if (ambiguousElseClause) {
cc.beginBlock();
}
add("if(");
add(first);
add(")");
if (hasElse) {
addNonEmptyExpression(
first.getNext(), Context.BEFORE_DANGLING_ELSE, false);
add("else");
addNonEmptyExpression(
last, getContextForNonEmptyExpression(context), false);
} else {
addNonEmptyExpression(first.getNext(), Context.OTHER, false);
Preconditions.checkState(childCount == 2);
}
if (ambiguousElseClause) {
cc.endBlock();
}
break;
case Token.NULL:
case Token.THIS:
case Token.FALSE:
case Token.TRUE:
Preconditions.checkState(childCount == 0);
add(Node.tokenToName(type));
break;
case Token.CONTINUE:
Preconditions.checkState(childCount <= 1);
add("continue");
if (childCount == 1) {
add(" ");
add(first);
}
cc.endStatement();
break;
case Token.DEBUGGER:
Preconditions.checkState(childCount == 0);
add("debugger");
cc.endStatement();
break;
case Token.BREAK:
Preconditions.checkState(childCount <= 1);
add("break");
if (childCount
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS> == 1) {
add(" ");
add(first);
}
cc.endStatement();
break;
case Token.EXPR_VOID:
case Token.EXPR_RESULT:
if (type == Token.EXPR_VOID && validation) {
throw new Error("Unexpected EXPR_VOID. Should be EXPR_RESULT.");
}
Preconditions.checkState(childCount == 1);
add(first, Context.START_OF_EXPR);
cc.endStatement();
break;
case Token.NEW:
add("new ");
int precedence = NodeUtil.precedence(type);
// If the first child contains a CALL, then claim higher precedence
// to force parens. Otherwise, when parsed, NEW will bind to the
// first viable parens
if (NodeUtil.containsCall(first)) {
precedence = NodeUtil.precedence(first.getType()) + 1;
}
addExpr(first, precedence);
// '()' is optional when no arguments are present
Node next = first.getNext();
if (next != null) {
add("(");
addList(next);
add(")");
}
break;
case Token.STRING:
Preconditions.checkState(childCount == 0);
add(jsString(n.getString(), outputCharsetEncoder));
break;
case Token.DELPROP:
Preconditions.checkState(childCount == 1);
add("delete ");
add(first);
break;
case Token.OBJECTLIT: {
Preconditions.checkState(childCount % 2 == 0);
boolean needsParens = (context == Context.START_OF_EXPR);
if (needsParens) {
add("(");
}
add("{");
for (Node c = first; c != null; c = c.getNext().getNext()) {
if (c != first) {
cc.listSeparator();
}
// Object literal property names don't have to be quoted if they are
// not JavaScript keywords
if (c.getType() == Token.STRING &&
!TokenStream.isKeyword(c.getString()) &&
TokenStream.isJSIdentifier(c.getString()) &&
// do not encode literally any non-literal characters that were
// unicode escaped.
NodeUtil.isLatin(c.getString()))
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS> {
add(c.getString());
} else {
addExpr(c, 1);
}
add(":");
addExpr(c.getNext(), 1);
}
add("}");
if (needsParens) {
add(")");
}
break;
}
case Token.SWITCH:
add("switch(");
add(first);
add(")");
cc.beginBlock();
addAllSiblings(first.getNext());
cc.endBlock(context == Context.STATEMENT);
break;
case Token.CASE:
Preconditions.checkState(childCount == 2);
add("case ");
add(first);
addCaseBody(last);
break;
case Token.DEFAULT:
Preconditions.checkState(childCount == 1);
add("default");
addCaseBody(first);
break;
case Token.LABEL:
Preconditions.checkState(childCount == 2);
add(first);
add(":");
addNonEmptyExpression(
last, getContextForNonEmptyExpression(context), true);
break;
// This node is auto generated in anonymous functions and should just get
// ignored for our purposes.
case Token.SETNAME:
break;
default:
throw new Error("Unknown type " + type + "\n" + n.toStringTree());
}
cc.endSourceMapping(n);
}
/**
* Adds a block or expression, substituting a VOID with an empty statement.
* This is used for "for (...);" and "if (...);" type statements.
*
* @param n The node to print.
* @param context The context to determine how the node should be printed.
*/
private void addNonEmptyExpression(
Node n, Context context, boolean allowNonBlockChild) {
Node nodeToProcess = n;
if (!allowNonBlockChild && n.getType() != Token.BLOCK) {
if (validation) {
throw new Error("Missing BLOCK child.");
}
}
// Strip unneeded blocks, that is blocks with <2 children unless
// the CodePrinter specifically wants to keep them.
if (n.getType() == Token.BLOCK ) {
int count = getNonEmptyChildCount(n);
if (count == 0) {
cc.endStatement(true);
return;
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>
}
if (count == 1) {
// Hack around a couple of browser bugs:
// Safari needs a block around function declarations.
// IE6/7 needs a block around DOs.
Node firstAndOnlyChild = getFirstNonEmptyChild(n);
boolean alwaysWrapInBlock = cc.shouldPreserveExtraBlocks();
if (alwaysWrapInBlock ||
firstAndOnlyChild.getType() == Token.FUNCTION ||
firstAndOnlyChild.getType() == Token.DO) {
cc.beginBlock();
add(firstAndOnlyChild, Context.STATEMENT);
cc.maybeLineBreak();
cc.endBlock(context == Context.STATEMENT);
return;
} else {
// Continue with the only child.
nodeToProcess = firstAndOnlyChild;
}
}
}
if (nodeToProcess.getType() == Token.EMPTY) {
cc.endStatement(true);
} else {
add(nodeToProcess, context);
// VAR doesn't include ';' since it gets used in expressions - so any
// VAR in a statement context needs a call to endStatement() here.
if (nodeToProcess.getType() == Token.VAR) {
cc.endStatement();
}
}
}
/**
* Adds a node at the left-hand side of an expression. Unlike
* {@link #addExpr(Node,int)}, this preserves information about the context.
*
* The left side of an expression is special because in the JavaScript
* grammar, certain tokens may be parsed differently when they are at
* the beginning of a statement. For example, "{}" is parsed as a block,
* but "{'x': 'y'}" is parsed as an object literal.
*/
void addLeftExpr(Node n, int minPrecedence, Context context) {
addExpr(n, minPrecedence, context);
}
void addExpr(Node n, int minPrecedence) {
addExpr(n, minPrecedence, Context.OTHER);
}
private void addExpr(Node n, int minPrecedence, Context context) {
if ((NodeUtil.precedence(n.getType()) < minPrecedence) ||
((context == Context.IN_FOR_INIT_CLAUSE) &&
(n.getType() == Token.IN))
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>){
add("(");
add(n, clearContextForNoInOperator(context));
add(")");
} else {
add(n, context);
}
}
void addList(Node firstInList) {
addList(firstInList, true, Context.OTHER);
}
void addList(Node firstInList, boolean isArrayOrFunctionArgument) {
addList(firstInList, isArrayOrFunctionArgument, Context.OTHER);
}
void addList(Node firstInList, boolean isArrayOrFunctionArgument,
Context lhsContext) {
for (Node n = firstInList; n != null; n = n.getNext()) {
boolean isFirst = n == firstInList;
if (isFirst) {
addLeftExpr(n, isArrayOrFunctionArgument ? 1 : 0, lhsContext);
} else {
cc.listSeparator();
addExpr(n, isArrayOrFunctionArgument ? 1 : 0);
}
}
}
/**
* This function adds a comma-separated list as is specified by an ARRAYLIT
* node with the associated skipIndexes array. This is a space optimization
* since we avoid creating a whole Node object for each empty array literal
* slot.
* @param firstInList The first in the node list (chained through the next
* property).
* @param skipIndexes If not null, then the array of skipped entries in the
* array.
*/
void addList(Node firstInList, int[] skipIndexes) {
int nextSlot = 0;
int nextSkipSlot = 0;
for (Node n = firstInList; n != null; n = n.getNext()) {
while (skipIndexes != null && nextSkipSlot < skipIndexes.length) {
if (nextSlot == skipIndexes[nextSkipSlot]) {
cc.listSeparator();
nextSlot++;
nextSkipSlot++;
} else {
break;
}
}
if (n != firstInList) {
cc.listSeparator();
}
addExpr(n, 1);
nextSlot++;
}
}
void addCaseBody(Node caseBody) {
cc.beginCaseBody();
add(caseBody);
cc.endCaseBody();
}
void addAllSiblings(Node n) {
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>
for (Node c = n; c != null; c = c.getNext()) {
add(c);
}
}
/** Outputs a js string, using the optimal (single/double) quote character */
static String jsString(String s, CharsetEncoder outputCharsetEncoder) {
int singleq = 0, doubleq = 0;
// could count the quotes and pick the optimal quote character
for (int i = 0; i < s.length(); i++) {
switch (s.charAt(i)) {
case '"': doubleq++; break;
case '\'': singleq++; break;
}
}
String doublequote, singlequote;
char quote;
if (singleq < doubleq) {
// more double quotes so escape the single quotes
quote = '\'';
doublequote = "\"";
singlequote = "\\\'";
} else {
// more single quotes so escape the doubles
quote = '\"';
doublequote = "\\\"";
singlequote = "\'";
}
return strEscape(s, quote, doublequote, singlequote, "\\\\",
outputCharsetEncoder);
}
/** Escapes regular expression */
static String regexpEscape(String s, CharsetEncoder outputCharsetEncoder) {
return strEscape(s, '/', "\"", "'", "\\", outputCharsetEncoder);
}
/**
* Escapes the given string to a double quoted (") JavaScript/JSON string
*/
static String escapeToDoubleQuotedJsString(String s) {
return strEscape(s, '"', "\\\"", "\'", "\\\\", null);
}
/* If the user doesn't want to specify an output charset encoder, assume
they want Latin/ASCII characters only.
*/
static String regexpEscape(String s) {
return regexpEscape(s, null);
}
/** Helper to escape javascript string as well as regular expression */
static String strEscape(String s, char quote,
String doublequoteEscape,
String singlequoteEscape,
String backslashEscape,
CharsetEncoder outputCharsetEncoder) {
StringBuilder sb = new StringBuilder();
sb.append(quote);
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
switch (c) {
case '\n': sb.append("\\n"); break;
case
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS> '\r': sb.append("\\r"); break;
case '\t': sb.append("\\t"); break;
case '\\': sb.append(backslashEscape); break;
case '\"': sb.append(doublequoteEscape); break;
case '\'': sb.append(singlequoteEscape); break;
case '>': // Break --> into --\> or ]]> into ]]\>
if (i >= 2 &&
((s.charAt(i - 1) == '-' && s.charAt(i - 2) == '-') ||
(s.charAt(i - 1) == ']' && s.charAt(i - 2) == ']'))) {
sb.append("\\>");
} else {
sb.append(c);
}
break;
case '<': // Break </script into <\/script
final String END_SCRIPT = "/script";
if (s.regionMatches(true, i + 1, END_SCRIPT, 0,
END_SCRIPT.length())) {
sb.append("<\\");
} else {
sb.append(c);
}
break;
default:
// If we're given an outputCharsetEncoder, then check if the
// character can be represented in this character set.
if (outputCharsetEncoder != null) {
if (outputCharsetEncoder.canEncode(c)) {
sb.append(c);
} else {
// Unicode-escape the character.
appendHexJavaScriptRepresentation(sb, c);
}
} else {
// No charsetEncoder provided - pass straight latin characters
// through, and escape the rest. Doing the explicit character
// check is measurably faster than using the CharsetEncoder.
if (c > 0x1f && c <= 0x7f) {
sb.append(c);
} else {
// Other characters can be misinterpreted by some js parsers,
// or perhaps mangled by proxies along the way,
// so we play it safe and unicode escape them.
appendHexJavaScriptRepresentation(sb, c);
}
}
}
}
sb.append(quote);
return sb.toString();
}
static String identifierEscape(String s) {
// First check if escaping is needed at all -- in most cases it isn't.
if (NodeUtil
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>ertype of a record type
* of the form { b : TYPE_2, a : TYPE_1 } because B can be assigned to
* A and matches all constraints. Similarly, a defined type can be assigned
* to a record type so long as that defined type matches all property
* constraints of the record type. A record type of the form { a : A, b : B }
* can be assigned to a record of type { a : A }.
*
*
*/
public class RecordType extends PrototypeObjectType {
private static final long serialVersionUID = 1L;
private Map<String, JSType> properties = new HashMap<String, JSType>();
private boolean isFrozen = false;
/**
* Creates a record type.
*
* @param registry The type registry under which this type lives.
* @param properties A map of all the properties of this record type.
*/
RecordType(JSTypeRegistry registry, Map<String, JSType> properties) {
super(registry, null, null);
for (String property : properties.keySet()) {
defineDeclaredProperty(property, properties.get(property), false);
}
// Freeze the record type.
isFrozen = true;
}
@Override
public boolean equals(Object other) {
if (!(other instanceof RecordType)) {
return false;
}
// Compare properties.
RecordType otherRecord = (RecordType) other;
return otherRecord.properties.equals(properties);
}
@Override
public ObjectType getImplicitPrototype() {
return registry.getNativeObjectType(JSTypeNative.OBJECT_TYPE);
}
@Override
boolean defineProperty(String propertyName, JSType type,
boolean inferred, boolean inExterns) {
if (isFrozen) {
return false;
}
if (!inferred) {
properties.put(propertyName, type);
}
return super.defineProperty(propertyName, type, inferred, inExterns);
}
@Override
public JSType getLeastSupertype(JSType that) {
if (!that.isRecordType()) {
return super.getLeastSupertype(that);
}
RecordType thatRecord = (RecordType) that;
RecordTypeBuilder builder = new RecordTypeBuilder(registry);
// The least supertype consist of those properties of the record
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS> // type that both record types hold in common both by name and
// type of the properties themselves.
for (String property : properties.keySet()) {
if (thatRecord.hasProperty(property) &&
thatRecord.getPropertyType(property).equals(
getPropertyType(property))) {
builder.addProperty(property, getPropertyType(property));
}
}
return builder.build();
}
@Override
public JSType getGreatestSubtype(JSType that) {
if (that.isRecordType()) {
RecordType thatRecord = (RecordType) that;
RecordTypeBuilder builder = new RecordTypeBuilder(registry);
// The greatest subtype consists of those *unique* properties of both
// record types. If any property conflicts, then the NO_TYPE type
// is returned.
for (String property : properties.keySet()) {
if (thatRecord.hasProperty(property) &&
!thatRecord.getPropertyType(property).equals(
getPropertyType(property))) {
return registry.getNativeObjectType(JSTypeNative.NO_TYPE);
}
builder.addProperty(property, getPropertyType(property));
}
for (String property : thatRecord.properties.keySet()) {
if (!hasProperty(property)) {
builder.addProperty(property, thatRecord.getPropertyType(property));
}
}
return builder.build();
}
JSType greatestSubtype = super.getGreatestSubtype(that);
if (greatestSubtype.isNoObjectType() && !that.isNoObjectType()) {
// In this branch, the other type is some object type. We find
// the greatest subtype with the following algorithm:
// 1) For each property "x" of this record type, take the union
// of all classes with a property "x" with a compatible property type.
// and which are a subtype of {@code that}.
// 2) Take the intersection of all of these unions.
for (Map.Entry<String, JSType> entry : properties.entrySet()) {
String propName = entry.getKey();
JSType propType = entry.getValue();
UnionTypeBuilder builder = new UnionTypeBuilder(registry);
for (ObjectType alt : registry.getTypesWithProperty(propName)) {
JSType altPropType = alt.getPropertyType(propName);
if (
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>altPropType != null && !alt.equals(this) &&
alt.isSubtype(that) &&
(propType.isUnknownType() || altPropType.isUnknownType() ||
altPropType.equals(propType))) {
builder.addAlternate(alt);
}
}
greatestSubtype = greatestSubtype.getLeastSupertype(builder.build());
}
}
return greatestSubtype;
}
@Override
public boolean isRecordType() {
return true;
}
@Override
public boolean isSubtype(JSType that) {
if (JSType.isSubtype(this, that)) {
return true;
}
// Top of the record types is the empty record, or OBJECT_TYPE.
if (registry.getNativeObjectType(
JSTypeNative.OBJECT_TYPE).isSubtype(that)) {
return true;
}
// A type is a subtype of a record type if it itself is a record
// type and it has at least the same members as the parent record type
// with the same types.
if (!that.isRecordType()) {
return false;
}
return RecordType.isSubtype(this, (RecordType) that);
}
/** Determines if typeA is a subtype of typeB */
static boolean isSubtype(ObjectType typeA, RecordType typeB) {
// typeA is a subtype of record type typeB iff:
// 1) typeA has all the properties declared in typeB.
// 2) And for each property of typeB,
// 2a) if the property of typeA is declared, it must be equal
// to the type of the property of typeB,
// 2b) otherwise, it must be a subtype of the property of typeB.
//
// To figure out why this is true, consider the following pseudo-code:
// /** @type {{a: (Object,null)}} */ var x;
// /** @type {{a: !Object}} */ var y;
// var z = {a: {}};
// x.a = null;
//
// y cannot be assigned to x, because line 4 would violate y's declared
// properties. But z can be assigned to x. Even though z and y are the
// same type, the properties of z are inferred--
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>and so an assignment
// to the property of z would not violate any restrictions on it.
for (String property : typeB.properties.keySet()) {
if (!typeA.hasProperty(property)) {
return false;
}
JSType propA = typeA.getPropertyType(property);
JSType propB = typeB.getPropertyType(property);
if (!propA.isUnknownType() && !propB.isUnknownType()) {
if (typeA.isPropertyTypeDeclared(property)) {
if (!propA.equals(propB)) {
return false;
}
} else {
if (!propA.isSubtype(propB)) {
return false;
}
}
}
}
return true;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("{ ");
int i = 0;
for (String property : properties.keySet()) {
if (i > 0) {
sb.append(", ");
}
sb.append(property);
sb.append(" : ");
sb.append(properties.get(property).toString());
++i;
}
sb.append(" }");
return sb.toString();
}
@Override
JSType resolveInternal(ErrorReporter t, StaticScope<JSType> scope) {
for (Map.Entry<String, JSType> entry : properties.entrySet()) {
JSType type = entry.getValue();
JSType resolvedType = type.resolve(t, scope);
if (type != resolvedType) {
properties.put(entry.getKey(), resolvedType);
}
}
return super.resolveInternal(t, scope);
}
}
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS> Create an exception with the specified detail message.
*
* Errors internal to the JavaScript engine will simply throw a
* RuntimeException.
*
* @param sourceName the name of the source reponsible for the error
* @param lineNumber the line number of the source
* @param columnNumber the columnNumber of the source (may be zero if
* unknown)
* @param lineSource the source of the line containing the error (may be
* null if unknown)
*/
EcmaError(String errorName, String errorMessage,
String sourceName, int lineNumber,
String lineSource, int columnNumber)
{
recordErrorOrigin(sourceName, lineNumber, lineSource, columnNumber);
this.errorName = errorName;
this.errorMessage = errorMessage;
}
@Override public String details()
{
return errorName+": "+errorMessage;
}
/**
* Gets the name of the error.
*
* ECMA edition 3 defines the following
* errors: EvalError, RangeError, ReferenceError,
* SyntaxError, TypeError, and URIError. Additional error names
* may be added in the future.
*
* See ECMA edition 3, 15.11.7.9.
*
* @return the name of the error.
*/
public String getName()
{
return errorName;
}
/**
* Gets the message corresponding to the error.
*
* See ECMA edition 3, 15.11.7.10.
*
* @return an implemenation-defined string describing the error.
*/
public String getErrorMessage()
{
return errorMessage;
}
/**
* @deprecated Use {@link RhinoException#sourceName()} from the super class.
*/
@Deprecated
public String getSourceName()
{
return sourceName();
}
/**
* @deprecated Use {@link RhinoException#lineNumber()} from the super class.
*/
@Deprecated
public int getLineNumber()
{
return lineNumber();
}
/**
* @deprecated
* Use {@link RhinoException#columnNumber()} from the super class.
*/
@Deprecated
public int getColumnNumber() {
return columnNumber();
}
/**
* @deprecated Use {@link RhinoException#
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>
*/
public class Scope implements StaticScope<JSType> {
private final Map<String, Var> vars = new LinkedHashMap<String, Var>();
private final Scope parent;
private final Node rootNode;
/** The type of {@code this} in the current scope. */
private final ObjectType thisType;
/** Whether this is a bottom scope for the purposes of type inference. */
private final boolean isBottom;
/** Stores info about a variable */
public static class Var implements StaticSlot<JSType> {
/** name */
String name;
/** Var node */
Node nameNode;
/**
* The variable's type.
*/
private JSType type;
/**
* The variable's doc info.
*/
private JSDocInfo info = null;
/**
* Whether the variable's type has been inferred or is declared. An inferred
* type may change over time (as more code is discovered), whereas a
* declared type is a static contract that must be matched.
*/
private final boolean typeInferred;
/** Input source */
CompilerInput input;
/** Whether the variable is a define */
boolean isDefine;
/**
* The index at which the var is declared. e..g if it's 0, it's the first
* declared variable in that scope
*/
int index;
/** The enclosing scope */
Scope scope;
/**
* Creates a variable.
*
* @param inferred whether its type is inferred (as opposed to declared)
*/
private Var(boolean inferred) {
this.typeInferred = inferred;
}
/**
* Gets the name of the variable.
*/
public String getName() {
return name;
}
/**
* Gets the parent of the name node.
*/
public Node getParentNode() {
return nameNode == null ? null : nameNode.getParent();
}
/**
* Gets the scope where this variable is declared.
*/
Scope getScope() {
return scope;
}
/**
* Returns the index within the scope stack.
* e.g. function Foo(a) { var b; function c(d) { } }
* a = 0, b = 1, c = 2, d = 3
*/
int getLocalVarIndex() {
int num = index;
Scope
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS> s = scope.getParent();
if (s == null) {
throw new IllegalArgumentException("Var is not local");
}
while (s.getParent() != null) {
num += s.getVarCount();
s = s.getParent();
}
return num;
}
/**
* Returns whether this is a global variable.
*/
public boolean isGlobal() {
return scope.isGlobal();
}
/**
* Returns whether this is a local variable.
*/
public boolean isLocal() {
return scope.isLocal();
}
/**
* Returns whether this is defined in an extern file.
*/
boolean isExtern() {
return input == null || input.isExtern();
}
/**
* Returns {@code true} if the variable is declared as a constant,
* based on the value reported by {@code NodeUtil}.
*/
public boolean isConst() {
return NodeUtil.isConstantName(nameNode);
}
/**
* Returns {@code true} if the variable is declared as a define.
* A variable is a define if it is annotaed by {@code @define}.
*/
public boolean isDefine() {
return isDefine;
}
public Node getInitialValue() {
Node parent = getParentNode();
return parent.getType() == Token.FUNCTION ?
parent : nameNode.getFirstChild();
}
/**
* Gets this variable's type. To know whether this type has been inferred,
* see {@code #isInferred()}.
*/
public JSType getType() {
return type;
}
/**
* Returns the name node that produced this variable.
*/
public Node getNameNode() {
return nameNode;
}
/**
* Gets the JSDocInfo for the variable.
*/
public JSDocInfo getJSDocInfo() {
return info;
}
/**
* Sets this variable's type.
* @throws IllegalStateException if the variable's type is not inferred
*/
void setType(JSType type) {
Preconditions.checkState(isTypeInferred());
this.type = type;
}
/**
* Returns whether this variable's type is inferred. To get the variable's
* type, see {@link #getType()}.
*/
public boolean isTypeInferred() {
return typeInferred;
}
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>
public String getInputName() {
if (input == null)
return "<non-file>";
else
return input.getName();
}
public boolean isNoShadow() {
if (info != null && info.isNoShadow()) {
return true;
} else {
return false;
}
}
@Override public boolean equals(Object other) {
if (!(other instanceof Var)) {
return false;
}
Var otherVar = (Var) other;
return otherVar.nameNode == nameNode;
}
@Override public int hashCode() {
return nameNode.hashCode();
}
@Override
public String toString() {
return "Scope.Var " + name;
}
}
/**
* Creates a Scope given the parent Scope and the root node of the scope.
* @param parent The parent Scope. Cannot be null.
* @param rootNode Typically the FUNCTION node.
*/
Scope(Scope parent, Node rootNode) {
Preconditions.checkNotNull(parent);
Preconditions.checkArgument(rootNode != parent.rootNode);
this.parent = parent;
this.rootNode = rootNode;
JSType nodeType = rootNode.getJSType();
if (nodeType != null && nodeType instanceof FunctionType) {
thisType = ((FunctionType) nodeType).getTypeOfThis();
} else {
thisType = parent.thisType;
}
this.isBottom = false;
}
/**
* Creates a global Scope.
* @param rootNode Typically the global BLOCK node.
*/
Scope(Node rootNode, AbstractCompiler compiler) {
this.parent = null;
this.rootNode = rootNode;
thisType = compiler.getTypeRegistry().getNativeObjectType(GLOBAL_THIS);
this.isBottom = false;
}
/**
* Creates a empty Scope (bottom of the lattice).
* @param rootNode Typically a FUNCTION node or the global BLOCK node.
* @param thisType the type of {@code this} in this scope
*/
Scope(Node rootNode, ObjectType thisType) {
this.parent = null;
this.rootNode = rootNode;
this.thisType = thisType;
this.isBottom = true;
}
/** Whether this is the bottom of the lattice. */
boolean isBottom
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>() {
return isBottom;
}
/**
* Gets the container node of the scope. This is typically the FUNCTION
* node or the global BLOCK/SCRIPT node.
*/
public Node getRootNode() {
return rootNode;
}
public Scope getParent() {
return parent;
}
Scope getGlobalScope() {
Scope result = this;
while (result.getParent() != null) {
result = result.getParent();
}
return result;
}
@Override
public StaticScope<JSType> getParentScope() {
return parent;
}
/**
* Gets the type of {@code this} in the current scope.
*/
public ObjectType getTypeOfThis() {
return thisType;
}
/**
* Declares a variable whose type is inferred.
*
* @param name name of the variable
* @param nameNode the NAME node declaring the variable
* @param type the variable's type
* @param input the input in which this variable is defined.
*/
Var declare(String name, Node nameNode, JSType type, CompilerInput input) {
return declare(name, nameNode, type, input, true);
}
/**
* Declares a variable.
*
* @param name name of the variable
* @param nameNode the NAME node declaring the variable
* @param type the variable's type
* @param input the input in which this variable is defined.
* @param inferred Whether this variable's type is inferred (as opposed
* to declared).
*/
Var declare(String name, Node nameNode,
JSType type, CompilerInput input, boolean inferred) {
Preconditions.checkState(name != null && name.length() > 0);
// Make sure that it's declared only once
Preconditions.checkState(vars.get(name) == null);
Var var = new Var(inferred);
var.name = name;
var.nameNode = nameNode;
var.type = type;
var.scope = this;
var.index = vars.size();
var.input = input;
// native variables do not have a name node.
// TODO(user): make Var abstract and have NativeVar, NormalVar.
JSDocInfo info = NodeUtil.getInfoForNameNode(nameNode);
var
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>.isDefine = info != null && info.isDefine();
var.info = info;
vars.put(name, var);
return var;
}
/**
* Undeclares a variable, to be used when the compiler optimizes out
* a variable and removes it from the scope.
*/
void undeclare(Var var) {
Preconditions.checkState(var.scope == this);
Preconditions.checkState(vars.get(var.name) == var);
vars.remove(var.name);
}
public StaticSlot<JSType> getSlot(String name) {
return getVar(name);
}
public StaticSlot<JSType> getOwnSlot(String name) {
return vars.get(name);
}
/**
* Returns the variable, may be null
*/
public Var getVar(String name) {
Var var = vars.get(name);
if (var != null) {
return var;
} else if (parent != null) { // Recurse up the parent Scope
return parent.getVar(name);
} else {
return null;
}
}
/**
* Returns true if a variable is declared.
*/
public boolean isDeclared(String name, boolean recurse) {
Scope scope = this;
if (scope.vars.containsKey(name))
return true;
if (scope.parent != null && recurse) {
return scope.parent.isDeclared(name, recurse);
}
return false;
}
/**
* Return an iterator over all of the variables declared in this scope.
*/
public Iterator<Var> getVars() {
return vars.values().iterator();
}
/**
* Returns number of variables in this scope
*/
public int getVarCount() {
return vars.size();
}
/**
* Returns whether this is the global scope.
*/
public boolean isGlobal() {
return parent == null;
}
/**
* Returns whether this is a local scope (i.e. not the global scope).
*/
public boolean isLocal() {
return !isGlobal();
}
}
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>import static com.google.javascript.rhino.jstype.JSTypeNative.NO_TYPE;
import static com.google.javascript.rhino.jstype.JSTypeNative.UNKNOWN_TYPE;
import java.io.Serializable;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
/**
* A builder for union types.
*
* @author nicksantos@google.com (Nick Santos)
*/
class UnionTypeBuilder implements Serializable {
private static final long serialVersionUID = 1L;
// If the best we can do is say "this object is one of twenty things",
// then we should just give up and admit that we have no clue.
private static final int MAX_UNION_SIZE = 20;
private final JSTypeRegistry registry;
private final List<JSType> alternates = Lists.newArrayList();
private boolean isAllType = false;
private boolean isNativeUnknownType = false;
private boolean areAllUnknownsChecked = true;
// Memoize the result, in case build() is called multiple times.
private JSType result = null;
UnionTypeBuilder(JSTypeRegistry registry) {
this.registry = registry;
}
/**
* Adds an alternate to the union type under construction. Returns this
* for easy chaining.
*/
UnionTypeBuilder addAlternate(JSType alternate) {
// build() returns the bottom type by default, so we can
// just bail out early here.
if (alternate.isNoType()) {
return this;
}
isAllType = isAllType || alternate.isAllType();
boolean isAlternateUnknown = alternate instanceof UnknownType;
isNativeUnknownType = isNativeUnknownType || isAlternateUnknown;
if (isAlternateUnknown) {
areAllUnknownsChecked = areAllUnknownsChecked &&
alternate.isCheckedUnknownType();
}
if (!isAllType && !isNativeUnknownType) {
if (alternate instanceof UnionType) {
UnionType union = (UnionType) alternate;
for (JSType unionAlt : union.getAlternates()) {
addAlternate(unionAlt);
}
} else {
if (!alternate.isUnknownType()) {
Iterator<JSType> it = alternates.iterator();
while
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS> (it.hasNext()) {
JSType current = it.next();
if (!current.isUnknownType()) {
if (alternate.isSubtype(current)) {
// Alternate is unnecessary.
return this;
} else if (current.isSubtype(alternate)) {
// Alternate makes current obsolete
it.remove();
}
}
}
}
alternates.add(alternate);
result = null; // invalidate the memoized result
}
} else {
result = null;
}
return this;
}
/**
* Creates a union.
* @return A UnionType if it has two or more alternates, the
* only alternate if it has one and otherwise {@code NO_TYPE}.
*/
JSType build() {
if (result == null) {
if (isAllType) {
result = registry.getNativeType(ALL_TYPE);
} else if (isNativeUnknownType) {
if (areAllUnknownsChecked) {
result = registry.getNativeType(CHECKED_UNKNOWN_TYPE);
} else {
result = registry.getNativeType(UNKNOWN_TYPE);
}
} else {
Set<JSType> alternateSet = Sets.newUnmodifiableHashSet(alternates);
int size = alternateSet.size();
if (size > MAX_UNION_SIZE) {
result = registry.getNativeType(UNKNOWN_TYPE);
} else {
if (size > 1) {
result = new UnionType(registry, alternateSet);
} else if (size == 1) {
result = alternates.iterator().next();
} else {
result = registry.getNativeType(NO_TYPE);
}
}
}
}
return result;
}
}
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>.
* <p>
* @param key the key used to index the value
* @param value the value to save
*/
public final void putThreadLocal(Object key, Object value)
{
if (sealed) onSealedMutation();
if (hashtable == null)
hashtable = new Hashtable<Object, Object>();
hashtable.put(key, value);
}
/**
* Remove values from thread-local storage.
* @param key the key for the entry to remove.
* @since 1.5 release 2
*/
public final void removeThreadLocal(Object key)
{
if (sealed) onSealedMutation();
if (hashtable == null)
return;
hashtable.remove(key);
}
/**
* @deprecated
* @see #FEATURE_DYNAMIC_SCOPE
* @see #hasFeature(int)
*/
@Deprecated
public final boolean hasCompileFunctionsWithDynamicScope()
{
return compileFunctionsWithDynamicScopeFlag;
}
/**
* @deprecated
* @see #FEATURE_DYNAMIC_SCOPE
* @see #hasFeature(int)
*/
@Deprecated
public final void setCompileFunctionsWithDynamicScope(boolean flag)
{
if (sealed) onSealedMutation();
compileFunctionsWithDynamicScopeFlag = flag;
}
/**
* Return the debugger context data associated with current context.
* @return the debugger data, or null if debugger is not attached
*/
public final Object getDebuggerContextData()
{
return debuggerData;
}
/**
* Implementation of {@link Context#hasFeature(int featureIndex)}.
* This can be used to customize {@link Context} without introducing
* additional subclasses.
*/
protected boolean hasFeature(int featureIndex)
{
int version;
switch (featureIndex) {
case Context.FEATURE_NON_ECMA_GET_YEAR:
/*
* During the great date rewrite of 1.3, we tried to track the
* evolving ECMA standard, which then had a definition of
* getYear which always subtracted 1900. Which we
* implemented, not realizing that it was incompatible with
* the old behavior... now, rather than thrash the behavior
* yet again, we've decided to leave it with
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>
/**
* Check whether the name is in the list of names of objects
* forcing the creation of activation objects.
*
* @param name the name of the object to test
*
* @return true if an function activation object is needed.
*/
public final boolean isActivationNeeded(String name)
{
return activationNames != null && activationNames.containsKey(name);
}
/**
* Remove a name from the list of names forcing the creation of real
* activation objects for functions.
*
* @param name the name of the object to remove from the list
*/
public void removeActivationName(String name)
{
if (sealed) onSealedMutation();
if (activationNames != null)
activationNames.remove(name);
}
private static String implementationVersion;
private boolean sealed;
private Object sealKey;
// for Objects, Arrays to tag themselves as being printed out,
// so they don't print themselves out recursively.
// Use ObjToIntMap instead of java.util.HashSet for JDK 1.1 compatibility
ObjToIntMap iterating;
Object interpreterSecurityDomain;
int version;
private ErrorReporter errorReporter;
private Locale locale;
private boolean generatingDebug;
private boolean generatingDebugChanged;
private boolean generatingSource=true;
boolean compileFunctionsWithDynamicScopeFlag;
boolean useDynamicScope;
private Object debuggerData;
private int enterCount;
private int optimizationLevel;
private Object propertyListeners;
private Hashtable<Object, Object> hashtable;
/**
* This is the list of names of objects forcing the creation of
* function activation records.
*/
Hashtable<Object, Object> activationNames;
// For the interpreter to store the last frame for error reports etc.
Object lastInterpreterFrame;
// For the interpreter to store information about previous invocations
// interpreter invocations
ObjArray previousInterpreterInvocations;
// For instruction counting (interpreter only)
int instructionCount;
int instructionThreshold;
// It can be used to return the second index-like result from function
int scratchIndex;
// It can be used to return the second uint32 result from function
long scratchUint32;
}
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>BadModuleReference(name, ref);
}
}
}
}
}
private void reportBadModuleReference(Name name, Ref ref) {
compiler.report(
JSError.make(ref.sourceName, ref.node, STRICT_MODULE_DEP_QNAME,
ref.module.getName(), name.declaration.module.getName(),
name.fullName()));
}
private void reportRefToUndefinedName(Name name, Ref ref) {
// grab the highest undefined ancestor to output in the warning message.
while (name.parent != null &&
name.parent.globalSets + name.parent.localSets == 0) {
name = name.parent;
}
// If this is an annotated EXPR-GET, don't do anything.
Node parent = ref.node.getParent();
if (parent.getType() == Token.EXPR_RESULT) {
JSDocInfo info = ref.node.getJSDocInfo();
if (info != null && info.hasTypedefType()) {
return;
}
}
compiler.report(
JSError.make(ref.sourceName, ref.node, level, UNDEFINED_NAME_WARNING,
name.fullName()));
}
/**
* Checks whether the given name is a property, and whether that property
* must be initialized with its full qualified name.
*/
private static boolean propertyMustBeInitializedByFullName(Name name) {
// If an object literal in the global namespace is never aliased,
// then all of its properties must be defined using its full qualified
// name. This implies that its properties must all be in the global
// namespace as well.
//
// The same is not true for FUNCTION and OTHER types, because their
// implicit prototypes have properties that are not captured by the global
// namespace.
return name.parent != null && name.parent.aliasingGets == 0 &&
name.parent.type == Name.Type.OBJECTLIT;
}
}
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS> String name = callName.getString();
int dollarIndex = name.lastIndexOf('$');
if (dollarIndex != -1) {
methodName = name.substring(dollarIndex + 1);
}
}
if (methodName != null) {
if (methodName.equals("inherits")) {
return SubclassType.INHERITS;
} else if (methodName.equals("mixin")) {
return SubclassType.MIXIN;
}
}
return null;
}
@Override
public boolean isSuperClassReference(String propertyName) {
return "superClass_".equals(propertyName);
}
/**
* Given a qualified name node, strip "prototype" off the end.
*
* Examples of this transformation:
* a.b.c => a.b.c
* a.b.c.prototype => a.b.c
*/
private Node stripPrototype(Node qualifiedName) {
if (qualifiedName.getType() == Token.GETPROP &&
qualifiedName.getLastChild().getString().equals("prototype")) {
return qualifiedName.getFirstChild();
}
return qualifiedName;
}
/**
* Exctracts X from goog.provide('X'), if the applied Node is goog.
*
* @return The extracted class name, or null.
*/
@Override
public String extractClassNameIfProvide(Node node, Node parent){
return extractClassNameIfGoog(node, parent, "goog.provide");
}
/**
* Exctracts X from goog.require('X'), if the applied Node is goog.
*
* @return The extracted class name, or null.
*/
@Override
public String extractClassNameIfRequire(Node node, Node parent){
return extractClassNameIfGoog(node, parent, "goog.require");
}
private static String extractClassNameIfGoog(Node node, Node parent,
String functionName){
String className = null;
if (NodeUtil.isExprCall(parent)) {
Node callee = node.getFirstChild();
if (callee != null && callee.getType() == Token.GETPROP) {
String qualifiedName = callee.getQualifiedName();
if ((functionName).equals(qualifiedName)) {
className = callee.getNext().getString();
}
}
}
return className;
}
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>
/**
* Use closure's implementation.
* @return closure's function name for exporting properties.
*/
@Override
public String getExportPropertyFunction() {
return "goog.exportProperty";
}
/**
* Use closure's implementation.
* @return closure's function name for exporting symbols.
*/
@Override
public String getExportSymbolFunction() {
return "goog.exportSymbol";
}
@Override
public List<String> identifyTypeDeclarationCall(Node n) {
Node callName = n.getFirstChild();
if ("goog.addDependency".equals(callName.getQualifiedName()) &&
n.getChildCount() >= 3) {
Node typeArray = callName.getNext().getNext();
if (typeArray.getType() == Token.ARRAYLIT) {
List<String> typeNames = Lists.newArrayList();
for (Node name = typeArray.getFirstChild(); name != null;
name = name.getNext()) {
if (name.getType() == Token.STRING) {
typeNames.add(name.getString());
}
}
return typeNames;
}
}
return null;
}
@Override
public String identifyTypeDefAssign(Node n) {
Node firstChild = n.getFirstChild();
int type = n.getType();
if (type == Token.ASSIGN) {
if (TYPEDEF_NAME.equals(n.getLastChild().getQualifiedName())) {
return firstChild.getQualifiedName();
}
} else if (type == Token.VAR && firstChild.hasChildren()) {
if (TYPEDEF_NAME.equals(
firstChild.getFirstChild().getQualifiedName())) {
return firstChild.getString();
}
}
return null;
}
@Override
public String getAbstractMethodName() {
return "goog.abstractMethod";
}
@Override
public String getSingletonGetterClassName(Node callNode) {
Node callName = callNode.getFirstChild();
if (!"goog.addSingletonGetter".equals(callName.getQualifiedName()) ||
callName.getChildCount() != 2) {
return null;
}
Node classNode = callName.getNext();
if (!classNode.isQualifiedName()) {
return null;
}
return callName.getNext().getQualifiedName();
}
@Override
public void applySingletonGetter(
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>FunctionType functionType,
FunctionType getterType, ObjectType objectType) {
functionType.defineDeclaredProperty("getInstance", getterType, false);
functionType.defineDeclaredProperty("instance_", objectType, false);
}
@Override
public String getGlobalObject() {
return "goog.global";
}
private final Set<String> propertyTestFunctions = ImmutableSet.of(
"goog.isDef", "goog.isNull", "goog.isDefAndNotNull",
"goog.isString", "goog.isNumber", "goog.isBoolean",
"goog.isFunction", "goog.isArray", "goog.isObject");
@Override
public boolean isPropertyTestFunction(Node call) {
Preconditions.checkArgument(call.getType() == Token.CALL);
return propertyTestFunctions.contains(
call.getFirstChild().getQualifiedName());
}
@Override
public ObjectLiteralCast getObjectLiteralCast(NodeTraversal t,
Node callNode) {
Preconditions.checkArgument(callNode.getType() == Token.CALL);
Node callName = callNode.getFirstChild();
if (!"goog.reflect.object".equals(callName.getQualifiedName()) ||
callName.getChildCount() != 2) {
return null;
}
Node typeNode = callName.getNext();
if (!typeNode.isQualifiedName()) {
return null;
}
Node objectNode = typeNode.getNext();
if (objectNode.getType() != Token.OBJECTLIT) {
t.getCompiler().report(JSError.make(t.getSourceName(), callNode,
OBJECTLIT_EXPECTED));
return null;
}
return new ObjectLiteralCast(typeNode.getQualifiedName(),
typeNode.getNext());
}
/**
* {@inheritDoc}
*/
@Override
public boolean isOptionalParameter(Node parameter) {
return false;
}
/**
* {@inheritDoc}
*/
@Override
public boolean isVarArgsParameter(Node parameter) {
return false;
}
/**
* {@inheritDoc}
*/
@Override
public boolean isPrivate(String name) {
return false;
}
}
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>
default:
Kit.codeBug();
}
return null;
}
private static class NumberNode extends Node {
private static final long serialVersionUID = 1L;
NumberNode(double number) {
super(Token.NUMBER);
this.number = number;
}
public NumberNode(double number, int lineno, int charno) {
super(Token.NUMBER, lineno, charno);
this.number = number;
}
@Override public double getDouble() {
return this.number;
}
@Override public void setDouble(double d) {
this.number = d;
}
@Override public boolean isEquivalentTo(Node node) {
return (node instanceof NumberNode
&& getDouble() == ((NumberNode) node).getDouble());
}
private double number;
}
private static class StringNode extends Node {
private static final long serialVersionUID = 1L;
StringNode(int type, String str) {
super(type);
if (null == str) {
throw new IllegalArgumentException("StringNode: str is null");
}
this.str = str;
}
StringNode(int type, String str, int lineno, int charno) {
super(type, lineno, charno);
if (null == str) {
throw new IllegalArgumentException("StringNode: str is null");
}
this.str = str;
}
/** returns the string content.
* @return non null.
*/
@Override public String getString() {
return this.str;
}
/** sets the string content.
* @param str the new value. Non null.
*/
@Override public void setString(String str) {
if (null == str) {
throw new IllegalArgumentException("StringNode: str is null");
}
this.str = str;
}
@Override public boolean isEquivalentTo(Node node) {
return (node instanceof StringNode &&
this.str.equals(((StringNode) node).str));
}
/**
* If the property is not defined, this was not a quoted key. The
* QUOTED_PROP int property is only assigned to STRING tokens used as
* object lit keys.
* @return true if this was a quoted string key in an object literal.
*/
@Override public boolean isQuotedString
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>() {
return getBooleanProp(QUOTED_PROP);
}
/**
* This should only be called for STRING nodes created in object lits.
*/
@Override public void setQuotedString() {
putBooleanProp(QUOTED_PROP, true);
}
private String str;
}
private static class PropListItem implements Serializable
{
private static final long serialVersionUID = 1L;
PropListItem next;
int type;
int intValue;
Object objectValue;
}
public Node(int nodeType) {
type = nodeType;
parent = null;
sourcePosition = -1;
}
public Node(int nodeType, Node child) {
Preconditions.checkArgument(child.parent == null,
"new child has existing parent");
Preconditions.checkArgument(child.next == null,
"new child has existing sibling");
type = nodeType;
parent = null;
first = last = child;
child.next = null;
child.parent = this;
sourcePosition = -1;
}
public Node(int nodeType, Node left, Node right) {
Preconditions.checkArgument(left.parent == null,
"first new child has existing parent");
Preconditions.checkArgument(left.next == null,
"first new child has existing sibling");
Preconditions.checkArgument(right.parent == null,
"second new child has existing parent");
Preconditions.checkArgument(right.next == null,
"second new child has existing sibling");
type = nodeType;
parent = null;
first = left;
last = right;
left.next = right;
left.parent = this;
right.next = null;
right.parent = this;
sourcePosition = -1;
}
public Node(int nodeType, Node left, Node mid, Node right) {
Preconditions.checkArgument(left.parent == null);
Preconditions.checkArgument(left.next == null);
Preconditions.checkArgument(mid.parent == null);
Preconditions.checkArgument(mid.next == null);
Preconditions.checkArgument(right.parent == null);
Preconditions.checkArgument(right.next == null);
type = nodeType;
parent = null;
first = left;
last = right;
left.next = mid;
left.parent
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS> = this;
mid.next = right;
mid.parent = this;
right.next = null;
right.parent = this;
sourcePosition = -1;
}
public Node(int nodeType, Node left, Node mid, Node mid2, Node right) {
Preconditions.checkArgument(left.parent == null);
Preconditions.checkArgument(left.next == null);
Preconditions.checkArgument(mid.parent == null);
Preconditions.checkArgument(mid.next == null);
Preconditions.checkArgument(mid2.parent == null);
Preconditions.checkArgument(mid2.next == null);
Preconditions.checkArgument(right.parent == null);
Preconditions.checkArgument(right.next == null);
type = nodeType;
parent = null;
first = left;
last = right;
left.next = mid;
left.parent = this;
mid.next = mid2;
mid.parent = this;
mid2.next = right;
mid2.parent = this;
right.next = null;
right.parent = this;
sourcePosition = -1;
}
public Node(int nodeType, int lineno, int charno) {
type = nodeType;
parent = null;
sourcePosition = mergeLineCharNo(lineno, charno);
}
public Node(int nodeType, Node child, int lineno, int charno) {
this(nodeType, child);
sourcePosition = mergeLineCharNo(lineno, charno);
}
public Node(int nodeType, Node left, Node right, int lineno, int charno) {
this(nodeType, left, right);
sourcePosition = mergeLineCharNo(lineno, charno);
}
public Node(int nodeType, Node left, Node mid, Node right,
int lineno, int charno) {
this(nodeType, left, mid, right);
sourcePosition = mergeLineCharNo(lineno, charno);
}
public Node(int nodeType, Node left, Node mid, Node mid2, Node right,
int lineno, int charno) {
this(nodeType, left, mid, mid2, right);
sourcePosition = mergeLineCharNo(lineno, charno);
}
public Node(int nodeType, Node[] children, int lineno,
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS> int charno) {
this(nodeType, children);
sourcePosition = mergeLineCharNo(lineno, charno);
}
public Node(int nodeType, Node[] children) {
this.type = nodeType;
parent = null;
if (children.length != 0) {
this.first = children[0];
this.last = children[children.length - 1];
for (int i = 1; i < children.length; i++) {
if (null != children[i - 1].next) {
// fail early on loops. implies same node in array twice
throw new IllegalArgumentException("duplicate child");
}
children[i - 1].next = children[i];
Preconditions.checkArgument(children[i - 1].parent == null);
children[i - 1].parent = this;
}
Preconditions.checkArgument(
children[children.length - 1].parent == null);
children[children.length - 1].parent = this;
if (null != this.last.next) {
// fail early on loops. implies same node in array twice
throw new IllegalArgumentException("duplicate child");
}
}
}
public static Node newNumber(double number) {
return new NumberNode(number);
}
public static Node newNumber(double number, int lineno, int charno) {
return new NumberNode(number, lineno, charno);
}
public static Node newString(String str) {
return new StringNode(Token.STRING, str);
}
public static Node newString(int type, String str) {
return new StringNode(type, str);
}
public static Node newString(String str, int lineno, int charno) {
return new StringNode(Token.STRING, str, lineno, charno);
}
public static Node newString(int type, String str, int lineno, int charno) {
return new StringNode(type, str, lineno, charno);
}
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
public boolean hasChildren() {
return first != null;
}
public Node getFirstChild() {
return first;
}
public Node getLastChild
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>() {
return last;
}
public Node getNext() {
return next;
}
public Node getChildBefore(Node child) {
if (child == first)
return null;
Node n = first;
while (n.next != child) {
n = n.next;
if (n == null)
throw new RuntimeException("node is not a child");
}
return n;
}
public Node getChildAtIndex(int i) {
Node n = first;
while (i > 0) {
n = n.next;
i--;
}
return n;
}
public Node getLastSibling() {
Node n = this;
while (n.next != null) {
n = n.next;
}
return n;
}
public void addChildToFront(Node child) {
Preconditions.checkArgument(child.parent == null);
Preconditions.checkArgument(child.next == null);
child.parent = this;
child.next = first;
first = child;
if (last == null) {
last = child;
}
}
public void addChildToBack(Node child) {
Preconditions.checkArgument(child.parent == null);
Preconditions.checkArgument(child.next == null);
child.parent = this;
child.next = null;
if (last == null) {
first = last = child;
return;
}
last.next = child;
last = child;
}
public void addChildrenToFront(Node children) {
for (Node child = children; child != null; child = child.next) {
Preconditions.checkArgument(child.parent == null);
child.parent = this;
}
Node lastSib = children.getLastSibling();
lastSib.next = first;
first = children;
if (last == null) {
last = lastSib;
}
}
public void addChildrenToBack(Node children) {
for (Node child = children; child != null; child = child.next) {
// Hmmm... IRFactory doesn't remove before calling this.
Preconditions.checkArgument(child.parent == null);
child.parent = this;
}
if (last != null) {
last.next = children;
}
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS> last = children.getLastSibling();
if (first == null) {
first = children;
}
}
/**
* Add 'child' before 'node'.
*/
public void addChildBefore(Node newChild, Node node) {
Preconditions.checkArgument(node != null,
"The existing child node of the parent should not be null.");
Preconditions.checkArgument(newChild.next == null,
"The new child node has siblings.");
Preconditions.checkArgument(newChild.parent == null,
"The new child node already has a parent.");
if (first == node) {
newChild.parent = this;
newChild.next = first;
first = newChild;
return;
}
Node prev = getChildBefore(node);
addChildAfter(newChild, prev);
}
/**
* Add 'child' after 'node'.
*/
public void addChildAfter(Node newChild, Node node) {
Preconditions.checkArgument(newChild.next == null,
"The new child node has siblings.");
Preconditions.checkArgument(newChild.parent == null,
"The new child node already has a parent.");
newChild.parent = this;
newChild.next = node.next;
node.next = newChild;
if (last == node) {
last = newChild;
}
}
/**
* Detach a child from its parent and siblings.
*/
public void removeChild(Node child) {
Node prev = getChildBefore(child);
if (prev == null)
first = first.next;
else
prev.next = child.next;
if (child == last) last = prev;
child.next = null;
child.parent = null;
}
/**
* Detaches child from Node and replaces it with newChild.
*/
public void replaceChild(Node child, Node newChild) {
Preconditions.checkArgument(newChild.next == null,
"The new child node has siblings.");
Preconditions.checkArgument(newChild.parent == null,
"The new child node already has a parent.");
// Copy over important information.
newChild.copyInformationFrom(child);
newChild.next = child.next;
newChild.parent = this;
if (child ==
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS> first) {
first = newChild;
} else {
Node prev = getChildBefore(child);
prev.next = newChild;
}
if (child == last)
last = newChild;
child.next = null;
child.parent = null;
}
public void replaceChildAfter(Node prevChild, Node newChild) {
Preconditions.checkArgument(prevChild.parent == this,
"prev is not a child of this node.");
Preconditions.checkArgument(newChild.next == null,
"The new child node has siblings.");
Preconditions.checkArgument(newChild.parent == null,
"The new child node already has a parent.");
// Copy over important information.
newChild.copyInformationFrom(prevChild);
Node child = prevChild.next;
newChild.next = child.next;
newChild.parent = this;
prevChild.next = newChild;
if (child == last)
last = newChild;
child.next = null;
child.parent = null;
}
private PropListItem lookupProperty(int propType)
{
PropListItem x = propListHead;
while (x != null && propType != x.type) {
x = x.next;
}
return x;
}
private PropListItem ensureProperty(int propType)
{
PropListItem item = lookupProperty(propType);
if (item == null) {
item = new PropListItem();
item.type = propType;
item.next = propListHead;
propListHead = item;
}
return item;
}
public void removeProp(int propType)
{
PropListItem x = propListHead;
if (x != null) {
PropListItem prev = null;
while (x.type != propType) {
prev = x;
x = x.next;
if (x == null) { return; }
}
if (prev == null) {
propListHead = x.next;
} else {
prev.next = x.next;
}
}
}
public Object getProp(int propType)
{
PropListItem item = lookupProperty(propType);
if (item == null) { return null; }
return item.objectValue;
}
public
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS> boolean getBooleanProp(int propType) {
return getIntProp(propType, 0) != 0;
}
public int getIntProp(int propType, int defaultValue)
{
PropListItem item = lookupProperty(propType);
if (item == null) { return defaultValue; }
return item.intValue;
}
public int getExistingIntProp(int propType)
{
PropListItem item = lookupProperty(propType);
if (item == null) { Kit.codeBug(); }
return item.intValue;
}
public void putProp(int propType, Object prop)
{
if (prop == null) {
removeProp(propType);
} else {
PropListItem item = ensureProperty(propType);
item.objectValue = prop;
}
}
public void putBooleanProp(int propType, boolean prop) {
putIntProp(propType, prop ? 1 : 0);
}
public void putIntProp(int propType, int prop)
{
PropListItem item = ensureProperty(propType);
item.intValue = prop;
}
// Gets all the property types, in sorted order.
private int[] getSortedPropTypes() {
int count = 0;
for (PropListItem x = propListHead; x != null; x = x.next) {
count++;
}
int[] keys = new int[count];
for (PropListItem x = propListHead; x != null; x = x.next) {
count--;
keys[count] = x.type;
}
Arrays.sort(keys);
return keys;
}
public int getLineno() {
return extractLineno(sourcePosition);
}
public int getCharno() {
return extractCharno(sourcePosition);
}
/** Can only be called when <tt>getType() == TokenStream.NUMBER</tt> */
public double getDouble() throws UnsupportedOperationException {
if (this.getType() == Token.NUMBER) {
throw new IllegalStateException(
"Number node not created with Node.newNumber");
} else {
throw new UnsupportedOperationException(
this + " is not a number node");
}
}
/** Can only be called when <tt>getType() == TokenStream.NUMBER</tt> */
public void set
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS> jsType.toString();
if (jsTypeString != null) {
sb.append(" : ");
sb.append(jsTypeString);
}
}
}
}
}
public String toStringTree() {
return toStringTreeImpl();
}
private String toStringTreeImpl() {
try {
StringBuffer s = new StringBuffer();
appendStringTree(s);
return s.toString();
} catch (IOException e) {
throw new RuntimeException("Should not happen\n" + e);
}
}
public void appendStringTree(Appendable appendable) throws IOException {
toStringTreeHelper(this, 0, appendable);
}
private static void toStringTreeHelper(Node n, int level, Appendable sb)
throws IOException
{
if (Token.printTrees) {
for (int i = 0; i != level; ++i) {
sb.append(" ");
}
sb.append(n.toString());
sb.append('\n');
for (Node cursor = n.getFirstChild(); cursor != null;
cursor = cursor.getNext())
{
toStringTreeHelper(cursor, level + 1, sb);
}
}
}
int type; // type of the node; Token.NAME for example
Node next; // next sibling
private Node first; // first element of a linked list of children
private Node last; // last element of a linked list of children
/**
* Linked list of properties. Since vast majority of nodes would have
* no more then 2 properties, linked list saves memory and provides
* fast lookup. If this does not holds, propListHead can be replaced
* by UintMap.
*/
private PropListItem propListHead;
/**
* COLUMN_BITS represents how many of the lower-order bits of
* sourcePosition are reserved for storing the column number.
* Bits above these store the line number.
* This gives us decent position information for everything except
* files already passed through a minimizer, where lines might
* be longer than 4096 characters.
*/
public static final int COLUMN_BITS = 12;
/**
* MAX_COLUMN_NUMBER represents the maximum column number that can
* be represented. JSCompiler's modifications to Rhino cause all
* tokens located beyond the maximum column to
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS> else {
return lineCharNo >>> COLUMN_BITS;
}
}
/**
* Extracts the character number and character number from a merged line
* char number (see {@link #mergeLineCharNo(int, int)}).
*/
protected static int extractCharno(int lineCharNo) {
if (lineCharNo == -1) {
return -1;
} else {
return lineCharNo & COLUMN_MASK;
}
}
//==========================================================================
// Iteration
/**
* <p>Return an iterable object that iterates over this nodes's children.
* The iterator does not support the optional operation
* {@link Iterator#remove()}.</p>
*
* <p>To iterate over a node's siblings, one can write</p>
* <pre>Node n = ...;
* for (Node child : n.children()) { ...</pre>
*/
public Iterable<Node> children() {
if (first == null) {
return Collections.emptySet();
} else {
return new SiblingNodeIterable(first);
}
}
/**
* <p>Return an iterable object that iterates over this nodes's siblings.
* The iterator does not support the optional operation
* {@link Iterator#remove()}.</p>
*
* <p>To iterate over a node's siblings, one can write</p>
* <pre>Node n = ...;
* for (Node sibling : n.siblings()) { ...</pre>
*/
public Iterable<Node> siblings() {
return new SiblingNodeIterable(this);
}
/**
* @see Node#siblings()
*/
private static final class SiblingNodeIterable
implements Iterable<Node>, Iterator<Node>
{
private final Node start;
private Node current;
private boolean used;
SiblingNodeIterable(Node start) {
this.start = start;
this.current = start;
this.used = false;
}
public Iterator<Node> iterator() {
if (!used) {
used = true;
return this;
} else {
// We have already used the current object as an iterator;
// we must create a new SiblingNodeIterable based on this
// iterable's start node.
//
// Since the primary use case for
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS> Node.children is in for
// loops, this branch is extremely unlikely.
return (new SiblingNodeIterable(start)).iterator();
}
}
public boolean hasNext() {
return current != null;
}
public Node next() {
if (current == null) {
throw new NoSuchElementException();
}
try {
return current;
} finally {
current = current.getNext();
}
}
public void remove() {
throw new UnsupportedOperationException();
}
}
//==========================================================================
// Accessors
public Node getParent() {
return parent;
}
/**
* Gets the ancestor node relative to this.
* @param level 0 = this, 1 = the parent, etc.
*/
public Node getAncestor(int level) {
Preconditions.checkArgument(level >= 0);
Node node = this;
while(node != null && level-- > 0) {
node = node.getParent();
}
return node;
}
/**
* Iterates all of the node's ancestors excluding itself.
*/
public AncestorIterable getAncestors() {
return new AncestorIterable(this.getParent());
}
/**
* Iterator to go up the ancestor tree.
*/
public static class AncestorIterable implements Iterable<Node> {
private Node cur;
/**
* @param cur The node to start.
*/
AncestorIterable(Node cur) {
this.cur = cur;
}
public Iterator<Node> iterator() {
return new Iterator<Node>() {
public boolean hasNext() {
return cur != null;
}
public Node next() {
if (!hasNext()) throw new NoSuchElementException();
Node n = cur;
cur = cur.getParent();
return n;
}
public void remove() {
throw new UnsupportedOperationException();
}
};
}
}
/**
* Check for one child more efficiently than by iterating over all the
* children as is done with Node.getChildCount().
* @return Whether the node has exactly one child.
*/
public boolean hasOneChild() {
return first != null && first == last;
}
/**
* Check for more than one child more efficiently than by iterating over all
* the children as is done with Node.getChildCount().
* @return Whether the node more than
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS> one child.
*/
public boolean hasMoreThanOneChild() {
return first != null && first != last;
}
public int getChildCount() {
int c = 0;
for (Node n = first; n != null; n = n.next)
c++;
return c;
}
// Intended for testing and verification only.
public boolean hasChild(Node child) {
for (Node n = first; n != null; n = n.getNext()) {
if (child == n) {
return true;
}
}
return false;
}
/**
* Checks if the subtree under this node is the same as another subtree.
* Returns null if it's equal, or a message describing the differences.
*/
public String checkTreeEquals(Node node2) {
NodeMismatch diff = checkTreeEqualsImpl(node2);
if (diff != null) {
return "Node tree inequality:" +
"\nTree1:\n" + toStringTree() +
"\n\nTree2:\n" + node2.toStringTree();
}
return null;
}
/**
* If this is a compilation pass and not a test, do not construct error
* strings. Instead return true if the trees are equal.
*/
public boolean checkTreeEqualsSilent(Node node2) {
return checkTreeEqualsImpl(node2) == null;
}
/**
* Compare this node to node2 recursively and return the first pair
* of nodes that differs doing a preorder depth-first traversal.
* Package private for testing. Returns null if the nodes are equivalent.
*/
NodeMismatch checkTreeEqualsImpl(Node node2) {
boolean eq = false;
if (type == node2.getType() &&
getChildCount() == node2.getChildCount() &&
getClass() == node2.getClass()) {
eq = this.isEquivalentTo(node2);
}
if (!eq) {
return new NodeMismatch(this, node2);
}
NodeMismatch res = null;
Node n, n2;
for (n = first, n2 = node2.first;
res == null && n != null;
n = n.next, n2 = n2.next) {
res = n.checkTreeEqualsImpl(n2
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>);
if (res != null) {
return res;
}
}
return res;
}
/**
* Checks if the subtree under this node is the same as another subtree
* including types. Returns null if it's equal, or a message describing the
* differences.
*/
public boolean checkTreeTypeAwareEqualsSilent(Node node2) {
return checkTreeTypeAwareEqualsImpl(node2) == null;
}
/**
* Compare this node to node2 recursively and return the first pair
* of nodes that differs doing a preorder depth-first traversal.
* Package private for testing. Returns null if the nodes are equivalent.
*/
NodeMismatch checkTreeTypeAwareEqualsImpl(Node node2) {
boolean eq = false;
if (type == node2.getType() &&
getChildCount() == node2.getChildCount() &&
getClass() == node2.getClass() &&
Objects.equal(jsType, node2.getJSType())) {
eq = this.isEquivalentTo(node2);
}
if (!eq) {
return new NodeMismatch(this, node2);
}
NodeMismatch res = null;
Node n, n2;
for (n = first, n2 = node2.first;
res == null && n != null;
n = n.next, n2 = n2.next) {
res = n.checkTreeTypeAwareEqualsImpl(n2);
if (res != null) {
return res;
}
}
return res;
}
public static String tokenToName(int token) {
switch (token) {
case Token.ERROR: return "error";
case Token.EOF: return "eof";
case Token.EOL: return "eol";
case Token.ENTERWITH: return "enterwith";
case Token.LEAVEWITH: return "leavewith";
case Token.RETURN: return "return";
case Token.GOTO: return "goto";
case Token.IFEQ: return "ifeq";
case Token.IFNE: return "ifne";
case Token.SETNAME: return "setname";
case Token.BITOR: return "bitor";
case Token.BITXOR: return "bitxor";
case Token.BIT
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS> node.getIntProp(INCRDECR_PROP, 0);
if (post1 != post2)
return false;
} else if (type == Token.STRING) {
int quoted1 = this.getIntProp(QUOTED_PROP, 0);
int quoted2 = node.getIntProp(QUOTED_PROP, 0);
if (quoted1 != quoted2)
return false;
}
return true;
}
public boolean hasSideEffects()
{
switch (type) {
case Token.EXPR_VOID:
case Token.COMMA:
if (last != null)
return last.hasSideEffects();
else
return true;
case Token.HOOK:
if (first == null ||
first.next == null ||
first.next.next == null)
Kit.codeBug();
return first.next.hasSideEffects() &&
first.next.next.hasSideEffects();
case Token.ERROR: // Avoid cascaded error messages
case Token.EXPR_RESULT:
case Token.ASSIGN:
case Token.ASSIGN_ADD:
case Token.ASSIGN_SUB:
case Token.ASSIGN_MUL:
case Token.ASSIGN_DIV:
case Token.ASSIGN_MOD:
case Token.ASSIGN_BITOR:
case Token.ASSIGN_BITXOR:
case Token.ASSIGN_BITAND:
case Token.ASSIGN_LSH:
case Token.ASSIGN_RSH:
case Token.ASSIGN_URSH:
case Token.ENTERWITH:
case Token.LEAVEWITH:
case Token.RETURN:
case Token.GOTO:
case Token.IFEQ:
case Token.IFNE:
case Token.NEW:
case Token.DELPROP:
case Token.SETNAME:
case Token.SETPROP:
case Token.SETELEM:
case Token.CALL:
case Token.THROW:
case Token.RETHROW:
case Token.SETVAR:
case Token.CATCH_SCOPE:
case Token.RETURN_RESULT:
case Token.SET_REF:
case Token.DEL_REF:
case Token.REF_CALL:
case Token.TRY:
case Token.SEMI:
case Token.INC:
case Token.DEC:
case Token.EXPORT:
case Token.IMPORT:
case Token.IF
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>scopedQualifiedName() {
switch (getType()) {
case Token.NAME:
return true;
case Token.GETPROP:
return getFirstChild().isUnscopedQualifiedName();
default:
return false;
}
}
//==========================================================================
// Mutators
/**
* Removes this node from its parent. Equivalent to:
* node.getParent().removeChild();
*/
public Node detachFromParent() {
Preconditions.checkState(parent != null);
parent.removeChild(this);
return this;
}
/**
* Removes the first child of Node. Equivalent to:
* node.removeChild(node.getFirstChild());
* @return The removed Node.
*/
public Node removeFirstChild() {
Node child = first;
if (child != null) {
removeChild(child);
}
return child;
}
/**
* @return A Node that is the head of the list of children.
*/
public Node removeChildren() {
Node children = first;
for (Node child = first; child != null; child = child.getNext()) {
child.parent = null;
}
first = null;
last = null;
return children;
}
/**
* Removes all children from this node and isolates the children from each
* other.
*/
public void detachChildren() {
for (Node child = first; child != null; ) {
Node nextChild = child.getNext();
child.parent = null;
child.next = null;
child = nextChild;
}
first = null;
last = null;
}
public Node removeChildAfter(Node prev) {
Preconditions.checkArgument(prev.parent == this,
"prev is not a child of this node.");
Preconditions.checkArgument(prev.next != null,
"no next sibling.");
Node child = prev.next;
prev.next = child.next;
if (child == last) last = prev;
child.next = null;
child.parent = null;
return child;
}
/**
* @return A detached clone of the Node, specifically excluding its
* children.
*/
public Node cloneNode() {
Node result;
try {
result = (Node) super.clone();
result.next = null;
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS> result.first = null;
result.last = null;
result.parent = null;
}
catch (CloneNotSupportedException e) {
throw new RuntimeException(e.getMessage());
}
return result;
}
/**
* @return A detached clone of the Node and all its children.
*/
public Node cloneTree() {
Node result = cloneNode();
for (Node n2 = getFirstChild(); n2 != null; n2 = n2.getNext()) {
Node n2clone = n2.cloneTree();
n2clone.parent = result;
if (result.last != null) {
result.last.next = n2clone;
}
if (result.first == null) {
result.first = n2clone;
}
result.last = n2clone;
}
return result;
}
/**
* Copies source file and name information from the other
* node given to the current node. Used for maintaining
* debug information across node append and remove operations.
*/
public void copyInformationFrom(Node other) {
if (getProp(ORIGINALNAME_PROP) == null) {
putProp(ORIGINALNAME_PROP, other.getProp(ORIGINALNAME_PROP));
}
if (getProp(SOURCEFILE_PROP) == null) {
putProp(SOURCEFILE_PROP, other.getProp(SOURCEFILE_PROP));
sourcePosition = other.sourcePosition;
}
}
/**
* Copies source file and name information from the other node to the
* entire tree rooted at this node.
*/
public void copyInformationFromForTree(Node other) {
copyInformationFrom(other);
for (Node child = getFirstChild();
child != null; child = child.getNext()) {
child.copyInformationFromForTree(other);
}
}
//==========================================================================
// Custom annotations
public JSType getJSType() {
return jsType;
}
public void setJSType(JSType jsType) {
this.jsType = jsType;
}
public FileLevelJsDocBuilder getJsDocBuilderForNode() {
return new FileLevelJsDocBuilder();
}
/**
* An inner class that provides back-door access to the license
* property of the JSDocInfo
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>#NAME} nodes
* used to define a {@link Token#FUNCTION}'s argument list.
*/
public void setOptionalArg(boolean optionalArg)
{
putBooleanProp(OPT_ARG_NAME, optionalArg);
}
/**
* Returns whether this node is an optional argument node. This
* method's return value is meaningful only on {@link Token#NAME} nodes
* used to define a {@link Token#FUNCTION}'s argument list.
*/
public boolean isOptionalArg()
{
return getBooleanProp(OPT_ARG_NAME);
}
/**
* Sets whether this is a synthetic block that should not be considered
* a real source block.
*/
public void setIsSyntheticBlock(boolean val) {
putBooleanProp(SYNTHETIC_BLOCK_PROP, val);
}
/**
* Returns whether this is a synthetic block that should not be considered
* a real source block.
*/
public boolean isSyntheticBlock() {
return getBooleanProp(SYNTHETIC_BLOCK_PROP);
}
/**
* Sets the ES5 directives on this node.
*/
public void setDirectives(Set<String> val) {
putProp(DIRECTIVES, val);
}
/**
* Returns the set of ES5 directives for this node.
*/
@SuppressWarnings("unchecked")
public Set<String> getDirectives() {
return (Set<String>) getProp(DIRECTIVES);
}
/**
* Sets whether this is a synthetic block that should not be considered
* a real source block.
*/
public void setWasEmptyNode(boolean val) {
putBooleanProp(EMPTY_BLOCK, val);
}
/**
* Returns whether this is a synthetic block that should not be considered
* a real source block.
*/
public boolean wasEmptyNode() {
return getBooleanProp(EMPTY_BLOCK);
}
/**
* Marks this function or constructor call node as having no side effects.
* This property is only meaningful for {@link Token#CALL} and
* {@link Token#NEW} nodes.
*/
public void setIsNoSideEffectsCall() {
Preconditions.checkArgument(
getType() == Token.CALL || getType() == Token.NEW,
"setIsNoSideEffectsCall only supports CALL and NEW nodes, got " +
Token
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>.name(getType()));
putBooleanProp(NO_SIDE_EFFECTS_CALL, true);
}
/**
* Returns true if this node is a function or constructor call that
* has no side effects.
*/
public boolean isNoSideEffectsCall() {
return getBooleanProp(NO_SIDE_EFFECTS_CALL);
}
/**
* This should only be called for STRING nodes created in object lits.
*/
public boolean isQuotedString() {
return false;
}
/**
* This should only be called for STRING nodes created in object lits.
*/
public void setQuotedString() {
Kit.codeBug();
}
static class NodeMismatch {
final Node nodeA;
final Node nodeB;
NodeMismatch(Node nodeA, Node nodeB) {
this.nodeA = nodeA;
this.nodeB = nodeB;
}
@Override public boolean equals(Object object) {
if (object instanceof NodeMismatch) {
NodeMismatch that = (NodeMismatch) object;
return that.nodeA.equals(this.nodeA) && that.nodeB.equals(this.nodeB);
}
return false;
}
@Override public int hashCode() {
return Objects.hashCode(nodeA, nodeB);
}
}
}
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>Override
public boolean isNullable() {
return false;
}
@Override
public TernaryValue testForEquality(JSType that) {
if (UNKNOWN.equals(super.testForEquality(that))) {
return UNKNOWN;
}
if (that.isUnknownType() || that.isSubtype(
getNativeType(JSTypeNative.OBJECT_NUMBER_STRING_BOOLEAN))) {
return UNKNOWN;
}
return FALSE;
}
@Override
public boolean isNumberValueType() {
return true;
}
@Override
public boolean matchesNumberContext() {
return true;
}
@Override
public boolean matchesStringContext() {
return true;
}
@Override
public boolean matchesObjectContext() {
// TODO(user): Revisit this for ES4, which is stricter.
return true;
}
@Override
public String toString() {
return "number";
}
@Override
public BooleanLiteralSet getPossibleToBooleanOutcomes() {
return BooleanLiteralSet.BOTH;
}
@Override
public <T> T visit(Visitor<T> visitor) {
return visitor.caseNumberType();
}
@Override
public JSType autoboxesTo() {
return getNativeType(JSTypeNative.NUMBER_OBJECT_TYPE);
}
}
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS> constructor;
InstanceObjectType(JSTypeRegistry registry, FunctionType constructor) {
this(registry, constructor, false);
}
InstanceObjectType(JSTypeRegistry registry, FunctionType constructor,
boolean isNativeType) {
super(registry, null, null, isNativeType);
Preconditions.checkNotNull(constructor);
this.constructor = constructor;
}
@Override
public String getReferenceName() {
return getConstructor().getReferenceName();
}
@Override
public boolean hasReferenceName() {
return getConstructor().hasReferenceName();
}
@Override
public ObjectType getImplicitPrototype() {
return getConstructor().getPrototype();
}
@Override
public FunctionType getConstructor() {
return constructor;
}
@Override
boolean defineProperty(String name, JSType type, boolean inferred,
boolean inExterns) {
ObjectType proto = getImplicitPrototype();
if (proto != null && proto.hasOwnDeclaredProperty(name)) {
return false;
}
return super.defineProperty(name, type, inferred, inExterns);
}
@Override
public String toString() {
return constructor.getReferenceName();
}
@Override
boolean isTheObjectType() {
return getConstructor().isNative() && "Object".equals(getReferenceName());
}
@Override
public boolean isInstanceType() {
return true;
}
@Override
public boolean isArrayType() {
return getConstructor().isNative() && "Array".equals(getReferenceName());
}
@Override
public boolean isStringObjectType() {
return getConstructor().isNative() && "String".equals(getReferenceName());
}
@Override
public boolean isBooleanObjectType() {
return getConstructor().isNative() && "Boolean".equals(getReferenceName());
}
@Override
public boolean isNumberObjectType() {
return getConstructor().isNative() && "Number".equals(getReferenceName());
}
@Override
public boolean isDateType() {
return getConstructor().isNative() && "Date".equals(getReferenceName());
}
@Override
public boolean isRegexpType() {
return getConstructor().isNative() && "RegExp".equals(getReferenceName());
}
@Override
public boolean isNominalType() {
return hasReferenceName();
}
@Override
public boolean equals(Object that) {
if
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS> (this == that) {
return true;
} else if (that instanceof JSType && this.isNominalType()) {
ObjectType thatObj = ObjectType.cast((JSType) that);
if (thatObj != null && thatObj.isNominalType()) {
return getReferenceName().equals(thatObj.getReferenceName());
}
}
return false;
}
/**
* If this is equal to a NamedType object, its hashCode must be equal
* to the hashCode of the NamedType object.
*/
@Override
public int hashCode() {
if (hasReferenceName()) {
return getReferenceName().hashCode();
} else {
return super.hashCode();
}
}
@Override
public Iterable<ObjectType> getCtorImplementedInterfaces() {
return getConstructor().getImplementedInterfaces();
}
// The owner will always be a resolved type, so there's no need to set
// the constructor in resolveInternal.
// (it would lead to infinite loops if we did).
// JSType resolveInternal(ErrorReporter t, StaticScope<JSType> scope);
}
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>WarningLevels(CompilerOptions options,
List<String> diagnosticGroups, CheckLevel level) {
for (String name : diagnosticGroups) {
DiagnosticGroup group = forName(name);
Preconditions.checkNotNull(group, "No warning class for name: " + name);
options.setWarningLevel(group, level);
}
}
}
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>1L;
NullType(JSTypeRegistry registry) {
super(registry);
}
@Override
public boolean isNullType() {
return true;
}
@Override
public boolean isNullable() {
return true;
}
@Override
public boolean matchesNumberContext() {
return true;
}
@Override
public boolean matchesObjectContext() {
return false;
}
@Override
public boolean matchesStringContext() {
return true;
}
@Override
public JSType restrictByNotNullOrUndefined() {
return registry.getNativeType(JSTypeNative.NO_TYPE);
}
@Override
public TernaryValue testForEquality(JSType that) {
if (UNKNOWN.equals(super.testForEquality(that))) {
return UNKNOWN;
}
if (that.isNullType() || that.isVoidType()) {
return TRUE;
}
if (that.isUnknownType() || that.isNullable()) {
return UNKNOWN;
}
return FALSE;
}
@Override
public String toString() {
return "null";
}
@Override
public BooleanLiteralSet getPossibleToBooleanOutcomes() {
return BooleanLiteralSet.FALSE;
}
@Override
public <T> T visit(Visitor<T> visitor) {
return visitor.caseNullType();
}
}
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS> com.google.javascript.rhino.ScriptRuntime;
import com.google.javascript.rhino.Token;
import static com.google.javascript.rhino.jstype.JSTypeNative.ALL_TYPE;
import static com.google.javascript.rhino.jstype.JSTypeNative.ARRAY_TYPE;
import static com.google.javascript.rhino.jstype.JSTypeNative.NO_TYPE;
import static com.google.javascript.rhino.jstype.JSTypeNative.UNKNOWN_TYPE;
import static com.google.javascript.rhino.jstype.JSTypeNative.VOID_TYPE;
import java.io.Serializable;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* The type registry is used to resolve named types.
*
* <p>This class is not thread-safe.
*
*
*/
public class JSTypeRegistry implements Serializable {
private static final long serialVersionUID = 1L;
// TODO(user): An instance of this class should be used during
// compilation. We also want to make all types' constructors package private
// and force usage of this registry instead. This will allow us to evolve the
// types without being tied by an open API.
private final transient ErrorReporter reporter;
// We use an Array instead of an immutable list because this lookup needs
// to be very fast. When it was an immutable list, we were spending 5% of
// CPU time on bounds checking inside get().
private final JSType[] nativeTypes;
private final Map<String, JSType> namesToTypes;
// Set of namespaces in which types (or other namespaces) exist.
private final Set<String> namespaces = new HashSet<String>();
// NOTE(nicksantos): This is a terrible terrible hack. When type expressions
// are evaluated, we need to be able to decide whether that type name
// resolves to a nullable type or a non-nullable type. Object types are
// nullable, but enum types are not.
//
// Notice that it's not good enough to just declare enum types sooner.
// For example, if we have
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS> // /** @enum {MyObject} */ var MyEnum = ...;
// we won't be to declare "MyEnum" without evaluating the expression
// {MyObject}, and following those dependencies starts to lead us into
// undecidable territory. Instead, we "pre-declare" enum types,
// so that the expression resolver can decide whether a given name is
// nullable or not.
private final Set<String> enumTypeNames = new HashSet<String>();
// Types that have been "forward-declared."
// If these types are not declared anywhere in the binary, we shouldn't
// try to type-check them at all.
private final Set<String> forwardDeclaredTypes = new HashSet<String>();
// A map of properties to the types on which those properties have been
// declared.
private final Map<String, Set<ObjectType>> typesIndexedByProperty =
Maps.newHashMap();
// A map of properties to the greatest subtype on which those properties have
// been declared. This is filled lazily from the types declared in
// typesIndexedByProperty.
private final Map<String, JSType> greatestSubtypeByProperty =
Maps.newHashMap();
// A map from interface name to types that implement it.
private final Multimap<String, FunctionType> interfaceToImplementors =
HashMultimap.create();
// All the unresolved named types.
private final Multimap<StaticScope<JSType>, NamedType> unresolvedNamedTypes =
ArrayListMultimap.create();
// All the resolved named types.
private final Multimap<StaticScope<JSType>, NamedType> resolvedNamedTypes =
ArrayListMultimap.create();
// NamedType warns about unresolved types in the last generation.
private boolean lastGeneration = true;
// The template type name.
private String templateTypeName;
// The template type.
private TemplateType templateType;
/**
* Constructs a new type registry populated with the built-in types.
*/
public JSTypeRegistry(ErrorReporter reporter) {
this.reporter = reporter;
nativeTypes = new JSType[JSTypeNative.values().length];
namesToTypes = new HashMap<String, JSType>();
resetForTypeCheck();
}
/**
* Reset to run the TypeCheck pass.
*/
public void resetForTypeCheck() {
typesIndexedByProperty.
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>.VOID_TYPE));
register(getNativeType(JSTypeNative.VOID_TYPE), "Undefined");
register(getNativeType(JSTypeNative.VOID_TYPE), "void");
register(getNativeType(JSTypeNative.FUNCTION_INSTANCE_TYPE), "Function");
}
private void register(JSType type) {
register(type, type.toString());
}
private void register(JSType type, String name) {
namesToTypes.put(name, type);
// Add all the namespaces in which this name lives.
while (name.indexOf('.') > 0) {
name = name.substring(0, name.lastIndexOf('.'));
namespaces.add(name);
}
}
private void registerNativeType(JSTypeNative typeId, JSType type) {
nativeTypes[typeId.ordinal()] = type;
}
/**
* Tells the type system that {@code owner} may have a property named
* {@code propertyName}. This allows the registry to keep track of what
* types a property is defined upon.
*
* This is NOT the same as saying that {@code owner} must have a property
* named type. ObjectType#hasProperty attempts to minimize false positives
* ("if we're not sure, then don't type check this property"). The type
* registry, on the other hand, should attempt to minimize false negatives
* ("if this property is assigned anywhere in the program, it must
* show up in the type registry").
*/
public void registerPropertyOnType(String propertyName, ObjectType owner) {
Set<ObjectType> typeSet = typesIndexedByProperty.get(propertyName);
if (typeSet == null) {
typesIndexedByProperty.put(propertyName, typeSet = Sets.newHashSet());
}
greatestSubtypeByProperty.remove(propertyName);
typeSet.add(owner);
}
/**
* Gets the greatest subtype of the {@code type} that has a property
* {@code propertyName} defined on it.
*/
public JSType getGreatestSubtypeWithProperty(
JSType type, String propertyName) {
if (greatestSubtypeByProperty.containsKey(propertyName)) {
return greatestSubtypeByProperty.get(propertyName)
.getGreatestSubtype(type);
}
if (typesIndexedByProperty.containsKey(propertyName)) {
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS> UnionTypeBuilder builder = new UnionTypeBuilder(this);
for (JSType alt : typesIndexedByProperty.get(propertyName)) {
builder.addAlternate(alt);
}
JSType built = builder.build();
greatestSubtypeByProperty.put(propertyName, built);
return built.getGreatestSubtype(type);
}
return getNativeType(NO_TYPE);
}
/**
* Returns whether the given property can possibly be set on the given type.
*/
public boolean canPropertyBeDefined(JSType type, String propertyName) {
if (typesIndexedByProperty.containsKey(propertyName)) {
for (JSType alt : typesIndexedByProperty.get(propertyName)) {
if (alt.isSubtype(type) || type.isSubtype(alt)) {
return true;
}
}
}
return false;
}
/**
* Returns each type that has a property {@code propertyName} defined on it.
*/
public Set<ObjectType> getTypesWithProperty(String propertyName) {
Set<ObjectType> typeSet = typesIndexedByProperty.get(propertyName);
if (typeSet == null) {
return Sets.newHashSet(getNativeObjectType(NO_TYPE));
}
return typeSet;
}
/**
* Increments the current generation. Clients must call this in order to
* move to the next generation of type resolution, allowing types to attempt
* resolution again.
*/
public void incrementGeneration() {
for (NamedType type : resolvedNamedTypes.values()) {
type.clearResolved();
}
unresolvedNamedTypes.putAll(resolvedNamedTypes);
resolvedNamedTypes.clear();
}
boolean isLastGeneration() {
return lastGeneration;
}
/**
* Sets whether this is the last generation. In the last generation,
* {@link NamedType} warns about unresolved types.
*/
public void setLastGeneration(boolean lastGeneration) {
this.lastGeneration = lastGeneration;
}
/**
* Tells the type system that {@code type} implements interface {@code
* InterfaceInstance}.
* {@code inter} must be an ObjectType for the instance of the interface as it
* could be a named type and not yet have the constructor.
*/
void registerTypeImplementingInterface(
FunctionType type, ObjectType interfaceInstance) {
interface
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>ToImplementors.put(interfaceInstance.getReferenceName(), type);
}
/**
* Returns a collection of types that directly implement {@code
* interfaceInstance}. Subtypes of implementing types are not guaranteed to
* be returned. {@code interfaceInstance} must be an ObjectType for the
* instance of the interface.
*/
public Collection<FunctionType> getDirectImplementors(
ObjectType interfaceInstance) {
return interfaceToImplementors.get(interfaceInstance.getReferenceName());
}
/**
* Records declared type names. Given the limited scopes of JavaScript, all
* named types are dumped in a common global scope. We may need to revise this
* assumption in the future.
*
* @param name The name of the type to be recorded.
* @param t The actual type being associated with the name.
* @return True if this name is not already defined, false otherwise.
*/
public boolean declareType(String name, JSType t) {
if (namesToTypes.containsKey(name)) {
return false;
}
register(t, name);
return true;
}
/**
* Records a forward-declared type name. We will not emit errors if this
* type name never resolves to anything.
*/
public void forwardDeclareType(String name) {
forwardDeclaredTypes.add(name);
}
/**
* Whether this is a forward-declared type name.
*/
public boolean isForwardDeclaredType(String name) {
return forwardDeclaredTypes.contains(name);
}
/** Determines whether the given JS package exists. */
public boolean hasNamespace(String name) {
return namespaces.contains(name);
}
/**
* Looks up a type by name.
*
* @param jsTypeName The name string.
* @return the corresponding JSType object or {@code null} it cannot be found
*/
public JSType getType(String jsTypeName) {
// TODO(user): Push every local type name out of namesToTypes so that
// NamedType#resolve is correct.
if (jsTypeName.equals(templateTypeName)) {
return templateType;
}
return namesToTypes.get(jsTypeName);
}
public JSType getNativeType(JSTypeNative typeId) {
return nativeTypes[typeId.ordinal()];
}
public ObjectType getNative
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS> {
return new FunctionType(
this, null, null, createParameters(parameterTypes), returnType);
}
/**
* Creates a function type. The last parameter type of the function is
* considered a variable length argument.
*
* @param returnType the function's return type
* @param parameterTypes the parameters' types
*/
public FunctionType createFunctionTypeWithVarArgs(
JSType returnType, List<JSType> parameterTypes) {
return new FunctionType(
this, null, null, createParametersWithVarArgs(parameterTypes),
returnType);
}
/**
* Creates a function type.
*
* @param returnType the function's return type
* @param parameterTypes the parameters' types
*/
public FunctionType createFunctionType(
JSType returnType, List<JSType> parameterTypes) {
return new FunctionType(
this, null, null, createParameters(parameterTypes), returnType);
}
/**
* Creates a function type. The last parameter type of the function is
* considered a variable length argument.
*
* @param returnType the function's return type
* @param parameterTypes the parameters' types
*/
public FunctionType createFunctionTypeWithVarArgs(
JSType returnType, JSType... parameterTypes) {
return new FunctionType(
this, null, null, createParametersWithVarArgs(parameterTypes), returnType);
}
/**
* Creates a function type which can act as a constructor.
*
* @param returnType the function's return type
* @param parameterTypes the parameters' types
*/
public FunctionType createConstructorType(
JSType returnType, JSType... parameterTypes) {
return createConstructorType(
null, null, createParameters(parameterTypes), returnType);
}
/**
* Creates a function type which can act as a constructor. The last
* parameter type of the constructor is considered a variable length argument.
*
* @param returnType the function's return type
* @param parameterTypes the parameters' types
*/
public FunctionType createConstructorTypeWithVarArgs(
JSType returnType, JSType... parameterTypes) {
return createConstructorType(
null, null, createParametersWithVarArgs(parameterTypes), returnType);
}
/**
* Creates a function type in which {@code this} refers to an object instance.
*
* @param instanceType the
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS> type of {@code this}
* @param returnType the function's return type
* @param parameterTypes the parameters' types
*/
public JSType createFunctionType(ObjectType instanceType,
JSType returnType, List<JSType> parameterTypes) {
return new FunctionType(this, null, null, createParameters(parameterTypes),
returnType, instanceType);
}
/**
* Creates a function type in which {@code this} refers to an object instance.
* The last parameter type of the function is considered a variable length
* argument.
*
* @param instanceType the type of {@code this}
* @param returnType the function's return type
* @param parameterTypes the parameters' types
*/
public JSType createFunctionTypeWithVarArgs(ObjectType instanceType,
JSType returnType, List<JSType> parameterTypes) {
return new FunctionType(this, null, null,
createParametersWithVarArgs(parameterTypes), returnType, instanceType);
}
/**
* Creates a tree hierarchy representing a typed argument list.
*
* @param parameterTypes the parameter types.
* @return a tree hierarchy representing a typed argument list.
*/
public Node createParameters(List<JSType> parameterTypes) {
return createParameters(
parameterTypes.toArray(new JSType[parameterTypes.size()]));
}
/**
* Creates a tree hierarchy representing a typed argument list. The last
* parameter type is considered a variable length argument.
*
* @param parameterTypes the parameter types. The last element of this array
* is considered a variable length argument.
* @return a tree hierarchy representing a typed argument list.
*/
public Node createParametersWithVarArgs(List<JSType> parameterTypes) {
return createParametersWithVarArgs(
parameterTypes.toArray(new JSType[parameterTypes.size()]));
}
/**
* Creates a tree hierarchy representing a typed argument list.
*
* @param parameterTypes the parameter types.
* @return a tree hierarchy representing a typed argument list.
*/
public Node createParameters(JSType... parameterTypes) {
return createParameters(false, parameterTypes);
}
/**
* Creates a tree hierarchy representing a typed argument list. The last
* parameter type is considered a variable length argument.
*
* @param parameterTypes the parameter types.
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS> true, false);
}
/**
* Creates an interface function type.
* @param name the function's name
* @param source the node defining this function. Its type
* ({@link Node#getType()}) must be {@link Token#FUNCTION}.
*/
public FunctionType createInterfaceType(String name, Node source) {
return new FunctionType(this, name, source);
}
/**
* Creates a parameterized type.
*/
public ParameterizedType createParameterizedType(
ObjectType objectType, JSType parameterType) {
return new ParameterizedType(this, objectType, parameterType);
}
/**
* Identifies the name of an enum before we actually declare it.
*/
public void identifyEnumName(String name) {
enumTypeNames.add(name);
}
/**
* Creates a RecordType from the nodes representing said record type.
* @param n The node with type info.
* @param sourceName The source file name.
* @param scope A scope for doing type name lookups.
*/
public JSType createRecordTypeFromNodes(Node n, String sourceName,
StaticScope<JSType> scope) {
RecordTypeBuilder builder = new RecordTypeBuilder(this);
// For each of the fields in the record type.
for (Node fieldTypeNode = n.getFirstChild();
fieldTypeNode != null;
fieldTypeNode = fieldTypeNode.getNext()) {
// Get the property's name.
Node fieldNameNode = fieldTypeNode;
boolean hasType = false;
if (fieldTypeNode.getType() == Token.COLON) {
fieldNameNode = fieldTypeNode.getFirstChild();
hasType = true;
}
String fieldName = fieldNameNode.getString();
// TODO(user): Move this into the lexer/parser.
// Remove the string literal characters around a field name,
// if any.
if (fieldName.startsWith("'") || fieldName.startsWith("\"")) {
fieldName = fieldName.substring(1, fieldName.length() - 1);
}
// Get the property's type.
JSType fieldType = null;
if (hasType) {
// We have a declared type.
fieldType = createFromTypeNodes(
fieldTypeNode.getLastChild(), sourceName, scope);
} else {
// Otherwise, the type is UNKNOWN.
fieldType =
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS> instanceof ObjectType) &&
!(enumTypeNames.contains(n.getString()))) {
Node typeList = n.getFirstChild();
if (typeList != null &&
("Array".equals(n.getString()) ||
"Object".equals(n.getString()))) {
JSType parameterType =
createFromTypeNodes(
typeList.getLastChild(), sourceName, scope);
namedType = new ParameterizedType(
this, (ObjectType) namedType, parameterType);
if (typeList.hasMoreThanOneChild()) {
JSType indexType =
createFromTypeNodes(
typeList.getFirstChild(), sourceName, scope);
namedType = new IndexedType(
this, (ObjectType) namedType, indexType);
}
}
return createNullableType(namedType);
} else {
return namedType;
}
case Token.FUNCTION:
ObjectType thisType = null;
Node current = n.getFirstChild();
if (current.getType() == Token.THIS) {
Node thisNode = current.getFirstChild();
thisType =
ObjectType.cast(
createFromTypeNodes(thisNode, sourceName, scope)
.restrictByNotNullOrUndefined());
if (thisType == null) {
reporter.warning(
ScriptRuntime.getMessage0("msg.jsdoc.function.thisnotobject"),
sourceName, thisNode.getLineno(), "", thisNode.getCharno());
}
current = current.getNext();
}
FunctionParamBuilder paramBuilder = new FunctionParamBuilder(this);
if (current.getType() == Token.LP) {
Node args = current.getFirstChild();
for (Node arg = current.getFirstChild(); arg != null;
arg = arg.getNext()) {
if (arg.getType() == Token.ELLIPSIS) {
if (arg.getChildCount() == 0) {
paramBuilder.addVarArgs(getNativeType(UNKNOWN_TYPE));
} else {
paramBuilder.addVarArgs(
createFromTypeNodes(
arg.getFirstChild(), sourceName, scope));
}
} else {
JSType type = createFromTypeNodes(arg, sourceName, scope);
if (arg.getType() == Token.EQUALS) {
boolean addSuccess = paramBuilder.addOptionalParams(type);
if (!addSuccess
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>) {
reporter.warning(
ScriptRuntime.getMessage0("msg.jsdoc.function.varargs"),
sourceName, arg.getLineno(), "", arg.getCharno());
}
} else {
paramBuilder.addRequiredParams(type);
}
}
}
current = current.getNext();
}
JSType returnType = createFromTypeNodes(current, sourceName, scope);
return new FunctionType(this, null, null, paramBuilder.build(),
returnType, thisType, null);
}
throw new IllegalStateException(
"Unexpected node in type expression: " + n.toString());
}
/**
* Sets the template type name.
*/
public void setTemplateTypeName(String name) {
templateTypeName = name;
templateType = new TemplateType(this, name);
}
/**
* Clears the template type name.
*/
public void clearTemplateTypeName() {
templateTypeName = null;
templateType = null;
}
}
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>;
}
public boolean isCheckedUnknownType() {
return false;
}
public boolean isUnionType() {
return false;
}
public boolean isFunctionType() {
return false;
}
public boolean isEnumElementType() {
return false;
}
public boolean isEnumType() {
return false;
}
public boolean isNamedType() {
return false;
}
public boolean isRecordType() {
return false;
}
public boolean isTemplateType() {
return false;
}
/**
* Tests whether this type is an {@code Object}, or any subtype thereof.
* @return {@code this <: Object}
*/
public boolean isObject() {
return false;
}
/**
* Whether this type is a {@link FunctionType} that is a constructor or a
* named type that points to such a type.
*/
public boolean isConstructor() {
return false;
}
/**
* Whether this type is a nominal type (a named instance object or
* a named enum).
*/
public boolean isNominalType() {
return false;
}
/**
* Whether this type is an Instance object of some constructor.
*/
public boolean isInstanceType() {
return false;
}
/**
* Whether this type is a {@link FunctionType} that is an interface or a named
* type that points to such a type.
*/
public boolean isInterface() {
return false;
}
/**
* Whether this type is a {@link FunctionType} that is an ordinary function or
* a named type that points to such a type.
*/
public boolean isOrdinaryFunction() {
return false;
}
/**
* This method relies on the fact that for the base {@link JSType}, only one
* instance of each sub-type will ever be created in a given registry, so
* there is no need to verify members. If the object pointers are not
* identical, then the type member must be different.
*/
@Override public boolean equals(Object jsType) {
if (jsType instanceof ProxyObjectType) {
return jsType.equals(this);
}
return this == jsType;
}
@Override
public int hashCode() {
return System.identityHashCode(this);
}
/**
* This
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS> mean compatible types that do not lead
* to step 22 of the definition of the Abstract Equality Comparison
* Algorithm (11.9.3, page 55–56) of the ECMA-262 specification.<p>
*/
public final boolean canTestForEqualityWith(JSType that) {
return this.testForEquality(that).equals(UNKNOWN);
}
/**
* Compares {@code this} and {@code that}.
* @return <ul>
* <li>{@link TernaryValue#TRUE} if the comparison of values of
* {@code this} type and {@code that} always succeed (such as
* {@code undefined} compared to {@code null})</li>
* <li>{@link TernaryValue#FALSE} if the comparison of values of
* {@code this} type and {@code that} always fails (such as
* {@code undefined} compared to {@code number})</li>
* <li>{@link TernaryValue#UNKNOWN} if the comparison can succeed or
* fail depending on the concrete values</li>
* </ul>
*/
public TernaryValue testForEquality(JSType that) {
if (that.isAllType() || that.isNoType() || that.isUnknownType()) {
return UNKNOWN;
}
if (that.isEnumElementType()) {
return that.testForEquality(this);
}
if (that instanceof UnionType) {
UnionType union = (UnionType) that;
TernaryValue result = null;
for (JSType t : union.alternates) {
TernaryValue test = this.testForEquality(t);
if (result == null) {
result = test;
} else if (!result.equals(test)) {
return UNKNOWN;
}
}
}
return null;
}
/**
* Tests whether {@code this} and {@code that} are meaningfully
* comparable using shallow comparison. By meaningfully, we mean compatible
* types that are not rejected by step 1 of the definition of the Strict
* Equality Comparison Algorithm (11.9.6, page 56–57) of the
* ECMA-262 specification.<p>
*/
public final boolean can
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS> ∧ Object} = {@code Number}</li>
* </ul>
* @return {@code this ∨ that}
*/
public JSType getGreatestSubtype(JSType that) {
if (that.isRecordType()) {
// Record types have their own implementation of getGreatestSubtype.
return that.getGreatestSubtype(this);
}
return getGreatestSubtype(this, that);
}
/**
* A generic implementation meant to be used as a helper for common
* getGreatestSubtype implementations.
*/
static JSType getGreatestSubtype(JSType thisType, JSType thatType) {
if (thatType.isEmptyType() || thatType.isAllType()) {
// Defer to the implementations of the end lattice elements when
// possible.
return thatType.getGreatestSubtype(thisType);
} else if (thisType.isUnknownType() || thatType.isUnknownType()) {
// The greatest subtype with any unknown type is the universal
// unknown type, unless the two types are equal.
return thisType.equals(thatType) ? thisType :
thisType.getNativeType(JSTypeNative.UNKNOWN_TYPE);
} else if (thisType.isSubtype(thatType)) {
return thisType;
} else if (thatType.isSubtype(thisType)) {
return thatType;
} else if (thisType.isUnionType()) {
return ((UnionType) thisType).meet(thatType);
} else if (thatType.isUnionType()) {
return ((UnionType) thatType).meet(thisType);
} else if (thisType.isObject() && thatType.isObject()) {
return thisType.getNativeType(JSTypeNative.NO_OBJECT_TYPE);
}
return thisType.getNativeType(JSTypeNative.NO_TYPE);
}
/**
* Computes the restricted type of this type knowing that the
* {@code ToBoolean} predicate has a specific value. For more information
* about the {@code ToBoolean} predicate, see
* {@link #getPossibleToBooleanOutcomes}.
*
* @param outcome the value of the {@code ToBoolean} predicate
*
* @return the restricted type, or the Any Type if the underlying
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS> type could
* not have yielded this ToBoolean value
*
* TODO(user): Move this method to the SemanticRAI and use the visit
* method of types to get the restricted type.
*/
public JSType getRestrictedTypeGivenToBooleanOutcome(boolean outcome) {
BooleanLiteralSet literals = getPossibleToBooleanOutcomes();
if (literals.contains(outcome)) {
return this;
} else {
return getNativeType(JSTypeNative.NO_TYPE);
}
}
/**
* Computes the set of possible outcomes of the {@code ToBoolean} predicate
* for this type. The {@code ToBoolean} predicate is defined by the ECMA-262
* standard, 3<sup>rd</sup> edition. Its behavior for simple types can be
* summarized by the following table:
* <table>
* <tr><th>type</th><th>result</th></tr>
* <tr><td>{@code undefined}</td><td>{false}</td></tr>
* <tr><td>{@code null}</td><td>{false}</td></tr>
* <tr><td>{@code boolean}</td><td>{true, false}</td></tr>
* <tr><td>{@code number}</td><td>{true, false}</td></tr>
* <tr><td>{@code string}</td><td>{true, false}</td></tr>
* <tr><td>{@code Object}</td><td>{true}</td></tr>
* </table>
* @return the set of boolean literals for this type
*/
public abstract BooleanLiteralSet getPossibleToBooleanOutcomes();
/**
* Computes the subset of {@code this} and {@code that} types if equality
* is observed. If a value {@code v1} of type {@code null} is equal to a value
* {@code v2} of type {@code (undefined,number)}, we can infer that the
* type of {@code v1} is {@code null} and the type of {@code v2} is
* {@code undefined}.
*
* @return a pair containing the restricted type of {@code this} as the first
* component and the restricted type of {@code that} as the second
* element. The returned pair is never {@code null}
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS> union type's constituents are a subtype of U. Formally<br>
* {@code (T<sub>1</sub>, …, T<sub>n</sub>) <: U} if and only
* {@code T<sub>k</sub> <: U} for all {@code k ∈ 1..n}.</li>
* <li>(union-r) — A type U is a subtype of a union type if it is a
* subtype of one of the union type's constituents. Formally<br>
* {@code U <: (T<sub>1</sub>, …, T<sub>n</sub>)} if and only
* if {@code U <: T<sub>k</sub>} for some index {@code k}.</li>
* <li>(objects) — an Object {@code O<sub>1</sub>} is a subtype
* of an object {@code O<sub>2</sub>} if it has more properties
* than {@code O<sub>2</sub>} and all common properties are
* pairwise subtypes.</li>
* </ul>
*
* @return {@code this <: that}
*/
public abstract boolean isSubtype(JSType that);
/**
* Whether this type is meaningfully different from {@code that} type.
* This is a trickier check than pure equality, because it has to properly
* handle unknown types.
*
* @see <a href="http://www.youtube.com/watch?v=_RpSv3HjpEw">Unknown
* unknowns</a>
*/
public boolean differsFrom(JSType that) {
// if there are no unknowns, just use normal equality.
if (!this.isUnknownType() && !that.isUnknownType()) {
return !this.equals(that);
}
// otherwise, they're different iff one is unknown and the other is not.
return this.isUnknownType() ^ that.isUnknownType();
}
/**
* A generic implementation meant to be used as a helper for common subtyping
* cases.
*/
static boolean isSubtype(JSType thisType, JSType thatType) {
// unknown
if
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS> (thatType.isUnknownType()) {
return true;
}
// equality
if (thisType.equals(thatType)) {
return true;
}
// all type
if (thatType.isAllType()) {
return true;
}
// unions
if (thatType instanceof UnionType) {
UnionType union = (UnionType)thatType;
for (JSType element : union.alternates) {
if (thisType.isSubtype(element)) {
return true;
}
}
}
// named types
if (thatType instanceof NamedType) {
return thisType.isSubtype(((NamedType)thatType).referencedType);
}
return false;
}
/**
* Visit this type with the given visitor.
* @see com.google.javascript.rhino.jstype.Visitor
* @return the value returned by the visitor
*/
public abstract <T> T visit(Visitor<T> visitor);
/**
* Resolve this type in the given scope.
*
* The returned value must be equal to {@code this}, as defined by
* {@link Object#equals}. It may or may not be the same object. This method
* may modify the internal state of {@code this}, as long as it does
* so in a way that preserves Object equality.
*
* For efficiency, we should only resolve a type once per compilation job.
* For incremental compilations, one compilation job may need the
* artifacts from a previous generation, so we will eventually need
* a generational flag instead of a boolean one.
*/
public final JSType resolve(ErrorReporter t, StaticScope<JSType> scope) {
if (resolved) {
// TODO(nicksantos): Check to see if resolve() looped back on itself.
// Preconditions.checkNotNull(resolveResult);
if (resolveResult == null) {
return registry.getNativeType(JSTypeNative.UNKNOWN_TYPE);
}
return resolveResult;
}
resolved = true;
resolveResult = resolveInternal(t, scope);
return resolveResult;
}
/**
* @see #resolve
*/
abstract JSType resolveInternal(ErrorReporter t, StaticScope<JSType> scope);
void setResolvedTypeInternal(JSType type) {
resolveResult = type
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>Param = null;
}
}
// Right now, the parser's type system doesn't have a good way
// to model optional arguments.
//
// Suppose we have
// function f(number, number) {}
// function g(number) {}
// If the second arg of f is optional, then f is a subtype of g,
// but g is not a subtype of f.
// If the second arg of f is required, then g is a subtype of f,
// but f is not a subtype of g.
//
// Until we model optional params, let's just punt on this.
// If one type has more arguments than the other, we won't check them.
//
// NOTE(nicksantos): This is described in Draft 2 of the ES4 spec,
// Section 3.4.6: Subtyping Function Types. It seems really
// strange but I haven't thought a lot about the implementation.
}
return true;
}
@Override
public boolean equals(Object object) {
// Please keep this method in sync with the hashCode() method below.
if (!(object instanceof ArrowType)) {
return false;
}
ArrowType that = (ArrowType) object;
// if both return types are specified, then they should be equal
if (returnType == null) {
if (that.returnType != null) {
return false;
}
} else {
if (that.returnType == null) {
return false;
}
if (!returnType.equals(that.returnType)) {
return false;
}
}
// if both types include parameters, the lists should be the same
if (parameters == null) {
return that.parameters == null;
} else if (that.parameters == null) {
return false;
}
Node thisParam = parameters.getFirstChild();
Node otherParam = that.parameters.getFirstChild();
while (thisParam != null && otherParam != null) {
JSType thisParamType = thisParam.getJSType();
JSType otherParamType = otherParam.getJSType();
if (thisParamType != null) {
// Both parameter lists give a type for this param, it should be equal
if (otherParamType != null &&
!thisParamType.equals(otherParamType)) {
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS> code will only run checks and not optimizations.
*/
abstract protected List<PassFactory> getChecks();
/**
* Gets the optimization passes to run.
*
* Optimization passes revolve around producing smaller and faster code.
* They should always run after checking passes.
*/
abstract protected List<PassFactory> getOptimizations();
/**
* Gets a graph of the passes run. For debugging.
*/
GraphvizGraph getPassGraph() {
LinkedDirectedGraph<String, String> graph = LinkedDirectedGraph.create();
Iterable<PassFactory> allPasses =
Iterables.concat(getChecks(), getOptimizations());
String lastPass = null;
String loopStart = null;
for (PassFactory pass : allPasses) {
String passName = pass.getName();
int i = 1;
while (graph.hasNode(passName)) {
passName = pass.getName() + (i++);
}
graph.createNode(passName);
if (loopStart == null && !pass.isOneTimePass()) {
loopStart = passName;
} else if (loopStart != null && pass.isOneTimePass()) {
graph.connect(lastPass, "loop", loopStart);
loopStart = null;
}
if (lastPass != null) {
graph.connect(lastPass, "", passName);
}
lastPass = passName;
}
return graph;
}
/**
* Create a type inference pass.
*/
final TypeInferencePass makeTypeInference(AbstractCompiler compiler) {
return new TypeInferencePass(
compiler, compiler.getReverseAbstractInterpreter(),
topScope, typedScopeCreator);
}
/**
* Create a type-checking pass.
*/
final TypeCheck makeTypeCheck(AbstractCompiler compiler) {
return new TypeCheck(
compiler,
compiler.getReverseAbstractInterpreter(),
compiler.getTypeRegistry(),
topScope,
typedScopeCreator,
options.reportMissingOverride,
options.reportUnknownTypes)
.reportMissingProperties(options.enables(
DiagnosticGroup.forType(TypeCheck.INEXISTENT_PROPERTY)));
}
final static void addPassFactoryBefore(
List<PassFactory> factoryList, PassFactory factory, String passName) {
for (int i = 0; i
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS> < factoryList.size(); i++) {
if (factoryList.get(i).getName().equals(passName)) {
factoryList.add(i, factory);
return;
}
}
throw new IllegalArgumentException(
"No factory named '" + passName + "' in the factory list");
}
/**
* Find the first pass provider that does not have a delegate.
*/
final PassConfig getBasePassConfig() {
PassConfig current = this;
while (current instanceof PassConfigDelegate) {
current = ((PassConfigDelegate) current).delegate;
}
return current;
}
/**
* Get intermediate state for a running pass config, so it can
* be paused and started again later.
*/
abstract State getIntermediateState();
/**
* Set the intermediate state for a pass config, to restart
* a compilation process that had been previously paused.
*/
abstract void setIntermediateState(State state);
/**
* An implementation of PassConfig that just proxies all its method calls
* into an inner class.
*/
static class PassConfigDelegate extends PassConfig {
private final PassConfig delegate;
PassConfigDelegate(PassConfig delegate) {
super(delegate.options);
this.delegate = delegate;
}
@Override protected List<PassFactory> getChecks() {
return delegate.getChecks();
}
@Override protected List<PassFactory> getOptimizations() {
return delegate.getOptimizations();
}
@Override ScopeCreator getScopeCreator() {
return delegate.getScopeCreator();
}
@Override Scope getTopScope() {
return delegate.getTopScope();
}
@Override State getIntermediateState() {
return delegate.getIntermediateState();
}
@Override void setIntermediateState(State state) {
delegate.setIntermediateState(state);
}
}
/**
* Intermediate state for a running pass configuration.
*/
static class State implements Serializable {
private static final long serialVersionUID = 1L;
final Map<String, Integer> cssNames;
final Set<String> exportedNames;
final CrossModuleMethodMotion.IdGenerator crossModuleIdGenerator;
final VariableMap variableMap;
final VariableMap propertyMap;
final VariableMap anonymousFunctionNameMap;
final FunctionNames functionNames;
State(Map<String, Integer> cssNames,
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS> Set<String> exportedNames,
CrossModuleMethodMotion.IdGenerator crossModuleIdGenerator,
VariableMap variableMap, VariableMap propertyMap,
VariableMap anonymousFunctionNameMap, FunctionNames functionNames) {
this.cssNames = cssNames;
this.exportedNames = exportedNames;
this.crossModuleIdGenerator = crossModuleIdGenerator;
this.variableMap = variableMap;
this.propertyMap = propertyMap;
this.anonymousFunctionNameMap = anonymousFunctionNameMap;
this.functionNames = functionNames;
}
}
}
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>import com.google.common.collect.Sets;
import com.google.javascript.rhino.ErrorReporter;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import java.util.Collections;
import java.util.List;
import java.util.Set;
/**
* This derived type provides extended information about a function, including
* its return type and argument types.<p>
*
* Note: the parameters list is the LP node that is the parent of the
* actual NAME node containing the parsed argument list (annotated with
* JSDOC_TYPE_PROP's for the compile-time type of each argument.
*
*
*/
public class FunctionType extends PrototypeObjectType {
private static final long serialVersionUID = 1L;
private enum Kind {
ORDINARY,
CONSTRUCTOR,
INTERFACE
}
/**
* {@code [[Call]]} property.
*/
private ArrowType call;
/**
* The {@code prototype} property. This field is lazily initialized by
* {@code #getPrototype()}. The most important reason for lazily
* initializing this field is that there are cycles in the native types
* graph, so some prototypes must temporarily be {@code null} during
* the construction of the graph.
*/
private FunctionPrototypeType prototype;
/**
* Whether a function is a constructor, an interface, or just an ordinary
* function.
*/
private final Kind kind;
/**
* The type of {@code this} in the scope of this function.
*/
private ObjectType typeOfThis;
/**
* The function node which this type represents. It may be {@code null}.
*/
private Node source;
/**
* The interfaces directly implemented by this function.
* It is only relevant for constructors. May not be {@code null}.
*/
private List<ObjectType> implementedInterfaces = ImmutableList.of();
/**
* The types which are subtypes of this function. It is only relevant for
* constructors and may be {@code null}.
*/
private List<FunctionType> subTypes;
/**
* The template type name. May be {@code null}.
*/
private String templateTypeName;
/**
* Creates a function type.
* @param registry the owner registry for this type
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>.kind = Kind.INTERFACE;
this.typeOfThis = new InstanceObjectType(registry, this);
}
@Override
public boolean isInstanceType() {
// The universal constructor is its own instance, bizarrely.
return equals(registry.getNativeType(U2U_CONSTRUCTOR_TYPE));
}
@Override
public boolean isConstructor() {
return kind == Kind.CONSTRUCTOR;
}
@Override
public boolean isInterface() {
return kind == Kind.INTERFACE;
}
@Override
public boolean isOrdinaryFunction() {
return kind == Kind.ORDINARY;
}
@Override
public boolean isFunctionType() {
return true;
}
@Override
public boolean canBeCalled() {
return true;
}
public Iterable<Node> getParameters() {
Node n = getParametersNode();
if (n != null) {
return n.children();
} else {
return Collections.emptySet();
}
}
/** Gets an LP node that contains all params. May be null. */
public Node getParametersNode() {
return call == null ? null : call.parameters;
}
/** Gets the minimum number of arguments that this function requires. */
public int getMinArguments() {
// NOTE(nicksantos): There are some native functions that have optional
// parameters before required parameters. This algorithm finds the position
// of the last required parameter.
int i = 0;
int min = 0;
for (Node n : getParameters()) {
i++;
if (!n.isOptionalArg() && !n.isVarArgs()) {
min = i;
}
}
return min;
}
/**
* Gets the maximum number of arguments that this function requires,
* or Integer.MAX_VALUE if this is a variable argument function.
*/
public int getMaxArguments() {
Node params = getParametersNode();
if (params != null) {
Node lastParam = params.getLastChild();
if (lastParam == null || !lastParam.isVarArgs()) {
return params.getChildCount();
}
}
return Integer.MAX_VALUE;
}
public JSType getReturnType() {
return call == null ? null : call.returnType;
}
/**
* Gets the {@code prototype}
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS> property of this function type. This is
* equivalent to {@code (ObjectType) getPropertyType("prototype")}.
*/
public FunctionPrototypeType getPrototype() {
// lazy initialization of the prototype field
if (prototype == null) {
setPrototype(new FunctionPrototypeType(registry, this, null));
}
return prototype;
}
/**
* Sets the prototype, creating the prototype object from the given
* base type.
* @param baseType The base type.
*/
public void setPrototypeBasedOn(ObjectType baseType) {
if (prototype == null) {
setPrototype(
new FunctionPrototypeType(
registry, this, baseType, isNativeObjectType()));
} else {
prototype.setImplicitPrototype(baseType);
}
}
/**
* Sets the prototype.
* @param prototype the prototype. If this value is {@code null} it will
* silently be discarded.
*/
public boolean setPrototype(FunctionPrototypeType prototype) {
if (prototype == null) {
return false;
}
// getInstanceType fails if the function is not a constructor
if (isConstructor() && prototype == getInstanceType()) {
return false;
}
this.prototype = prototype;
if (isConstructor() || isInterface()) {
FunctionType superClass = getSuperClassConstructor();
if (superClass != null) {
superClass.addSubType(this);
}
}
return true;
}
/**
* Returns all interfaces implemented by a class or its superclass and any
* superclasses for any of those interfaces. If this is called before all
* types are resolved, it may return an incomplete set.
*/
public Iterable<ObjectType> getAllImplementedInterfaces() {
Set<ObjectType> interfaces = Sets.newHashSet();
for (ObjectType type : getImplementedInterfaces()) {
addRelatedInterfaces(type, interfaces);
}
return interfaces;
}
private void addRelatedInterfaces(ObjectType instance, Set<ObjectType> set) {
FunctionType constructor = instance.getConstructor();
if (constructor != null) {
if (!constructor.isInterface()) {
return;
}
set.add(instance);
if (constructor.getSuperClassConstructor() != null) {
addRelatedInterfaces(
constructor.getSuperClassConstructor().getInstanceType(), set);
}
}
}
/** Returns interfaces
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS> implemented directly by a class or its superclass. */
public Iterable<ObjectType> getImplementedInterfaces() {
FunctionType superCtor = isConstructor() ?
getSuperClassConstructor() : null;
if (superCtor == null) {
return implementedInterfaces;
} else {
return Iterables.concat(
implementedInterfaces, superCtor.getImplementedInterfaces());
}
}
public void setImplementedInterfaces(List<ObjectType> implementedInterfaces) {
// Records this type for each implemented interface.
for (ObjectType type : implementedInterfaces) {
registry.registerTypeImplementingInterface(this, type);
}
this.implementedInterfaces = ImmutableList.copyOf(implementedInterfaces);
}
@Override
public boolean hasProperty(String name) {
return super.hasProperty(name) || "prototype".equals(name);
}
@Override
public boolean hasOwnProperty(String name) {
return super.hasOwnProperty(name) || "prototype".equals(name);
}
@Override
public JSType getPropertyType(String name) {
if ("prototype".equals(name)) {
return getPrototype();
} else {
if (!hasOwnProperty(name)) {
if ("call".equals(name)) {
// Define the "call" function lazily.
Node params = getParametersNode();
if (params == null) {
// If there's no params array, don't do any type-checking
// in this CALL function.
defineDeclaredProperty(name,
new FunctionType(registry, null, null,
null, getReturnType()),
false);
} else {
params = params.cloneTree();
Node thisTypeNode = Node.newString(Token.NAME, "thisType");
thisTypeNode.setJSType(
registry.createOptionalNullableType(getTypeOfThis()));
params.addChildToFront(thisTypeNode);
thisTypeNode.setOptionalArg(true);
defineDeclaredProperty(name,
new FunctionType(registry, null, null,
params, getReturnType()),
false);
}
} else if ("apply".equals(name)) {
// Define the "apply" function lazily.
FunctionParamBuilder builder = new FunctionParamBuilder(registry);
// Ecma-262 says that apply's second argument must be an Array
// or an arguments object. We don't model the arguments object
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>,
// so let's just be forgiving for now.
// TODO(nicksantos): Model the Arguments object.
builder.addOptionalParams(
registry.createNullableType(getTypeOfThis()),
registry.createNullableType(
registry.getNativeType(JSTypeNative.OBJECT_TYPE)));
defineDeclaredProperty(name,
new FunctionType(registry, null, null,
builder.build(), getReturnType()),
false);
}
}
return super.getPropertyType(name);
}
}
@Override
boolean defineProperty(String name, JSType type,
boolean inferred, boolean inExterns) {
if ("prototype".equals(name)) {
ObjectType objType = type.toObjectType();
if (objType != null) {
if (objType.equals(prototype)) {
return true;
}
return setPrototype(
new FunctionPrototypeType(
registry, this, objType, isNativeObjectType()));
} else {
return false;
}
}
return super.defineProperty(name, type, inferred, inExterns);
}
@Override
public boolean isPropertyTypeInferred(String property) {
return "prototype".equals(property) ||
super.isPropertyTypeInferred(property);
}
@Override
public JSType getLeastSupertype(JSType that) {
// NOTE(nicksantos): When we remove the unknown type, the function types
// form a lattice with the universal constructor at the top of the lattice,
// and the NoObject type at the bottom of the lattice.
//
// When we introduce the unknown type, it's much more difficult to make
// heads or tails of the partial ordering of types, because there's no
// clear hierarchy between the different components (parameter types and
// return types) in the ArrowType.
//
// Rather than make the situation more complicated by introducing new
// types (like unions of functions), we just fallback on the simpler
// approach of using the universal constructor and the AnyObject as
// the supremum and infinum of all function types.
if (isFunctionType() && that.isFunctionType()) {
if (equals(that)) {
return this;
}
JSType functionInstance = registry.getNativeType(
JSTypeNative.FUNCTION_INSTANCE_TYPE
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS>);
if (functionInstance.equals(that)) {
return that;
} else if (functionInstance.equals(this)) {
return this;
}
return registry.getNativeType(JSTypeNative.U2U_CONSTRUCTOR_TYPE);
}
return super.getLeastSupertype(that);
}
@Override
public JSType getGreatestSubtype(JSType that) {
if (isFunctionType() && that.isFunctionType()) {
if (equals(that)) {
return this;
}
JSType functionInstance = registry.getNativeType(
JSTypeNative.FUNCTION_INSTANCE_TYPE);
if (functionInstance.equals(that)) {
return this;
} else if (functionInstance.equals(this)) {
return that;
}
return registry.getNativeType(JSTypeNative.NO_OBJECT_TYPE);
}
return super.getGreatestSubtype(that);
}
/**
* Given a constructor or an interface type, get its superclass constructor
* or {@code null} if none exists.
*/
public FunctionType getSuperClassConstructor() {
Preconditions.checkArgument(isConstructor() || isInterface());
ObjectType maybeSuperInstanceType = getPrototype().getImplicitPrototype();
if (maybeSuperInstanceType == null) {
return null;
}
return maybeSuperInstanceType.getConstructor();
}
/**
* Given a constructor or an interface type, find out whether the unknown
* type is a supertype of the current type.
*/
public boolean hasUnknownSupertype() {
Preconditions.checkArgument(isConstructor() || isInterface());
Preconditions.checkArgument(!this.isUnknownType());
// Potential infinite loop if our type system messes up or someone defines
// a bad type. Otherwise the loop should always end.
FunctionType ctor = this;
while (true) {
ObjectType maybeSuperInstanceType =
ctor.getPrototype().getImplicitPrototype();
if (maybeSuperInstanceType == null) {
return false;
}
if (maybeSuperInstanceType.isUnknownType()) {
return true;
}
ctor = maybeSuperInstanceType.getConstructor();
if (ctor == null) {
return false;
}
Preconditions.checkState(ctor.isConstructor() || ctor.isInterface());
}
}
/**
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS> * Given a constructor or an interface type and a property, finds the
* top-most superclass that has the property defined (including this
* constructor).
*/
public JSType getTopMostDefiningType(String propertyName) {
Preconditions.checkState(isConstructor() || isInterface());
Preconditions.checkArgument(getPrototype().hasProperty(propertyName));
FunctionType ctor = this;
JSType topInstanceType;
do {
topInstanceType = ctor.getInstanceType();
ctor = ctor.getSuperClassConstructor();
} while (ctor != null && ctor.getPrototype().hasProperty(propertyName));
return topInstanceType;
}
/**
* Two function types are equal if their signatures match. Since they don't
* have signatures, two interfaces are equal if their names match.
*/
@Override
public boolean equals(Object otherType) {
if (!(otherType instanceof FunctionType)) {
return false;
}
FunctionType that = (FunctionType) otherType;
if (!that.isFunctionType()) {
return false;
}
if (this.isConstructor()) {
if (that.isConstructor()) {
return this == that;
}
return false;
}
if (this.isInterface()) {
if (that.isInterface()) {
return this.getReferenceName().equals(that.getReferenceName());
}
return false;
}
if (that.isInterface()) {
return false;
}
return this.typeOfThis.equals(that.typeOfThis) &&
this.call.equals(that.call);
}
@Override
public int hashCode() {
return isInterface() ? getReferenceName().hashCode() : call.hashCode();
}
public boolean hasEqualCallType(FunctionType otherType) {
return this.call.equals(otherType.call);
}
/**
* Informally, a function is represented by
* {@code function (params): returnType} where the {@code params} is a comma
* separated list of types, the first one being a special
* {@code this:T} if the function expects a known type for {@code this}.
*/
@Override
public String toString() {
if (this == registry.getNativeType(JSTypeNative.FUNCTION_INSTANCE_TYPE)) {
return "Function";
}
StringBuilder b =
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS> new StringBuilder(32);
b.append("function (");
int paramNum = (call == null || call.parameters == null) ?
0 : call.parameters.getChildCount();
boolean hasKnownTypeOfThis = !typeOfThis.isUnknownType();
if (hasKnownTypeOfThis) {
b.append("this:");
b.append(typeOfThis.toString());
}
if (paramNum > 0) {
if (hasKnownTypeOfThis) {
b.append(", ");
}
Node p = call.parameters.getFirstChild();
if (p.isVarArgs()) {
appendVarArgsString(b, p.getJSType());
} else {
b.append(p.getJSType().toString());
}
p = p.getNext();
while (p != null) {
b.append(", ");
if (p.isVarArgs()) {
appendVarArgsString(b, p.getJSType());
} else {
b.append(p.getJSType().toString());
}
p = p.getNext();
}
}
b.append(")");
if (call != null && call.returnType != null) {
b.append(": ");
b.append(call.returnType);
}
return b.toString();
}
/** Gets the string representation of a var args param. */
private void appendVarArgsString(StringBuilder builder, JSType paramType) {
if (paramType.isUnionType()) {
// Remove the optionalness from the var arg.
paramType = ((UnionType) paramType).getRestrictedUnion(
registry.getNativeType(JSTypeNative.VOID_TYPE));
}
builder.append("...[").append(paramType.toString()).append("]");
}
/**
* A function is a subtype of another if their call methods are related via
* subtyping and {@code this} is a subtype of {@code that} with regard to
* the prototype chain.
*/
@Override
public boolean isSubtype(JSType that) {
if (this.equals(that)) {
return true;
}
if (that.isFunctionType()) {
if (((FunctionType) that).isInterface()) {
// Any function can be assigned to an interface function.
return true;
}
if (this
Closure, 137
<FILEB>
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
<CHANGEE>
<CHANGES>
public static final String ARGUMENTS = "arguments";
<CHANGEE>
<CHANGES>
static class ContextualRenameInverter
implements ScopedCallback, CompilerPass {
<CHANGEE>
<CHANGES>
private Set<String> referencedNames = ImmutableSet.of();
<CHANGEE>
<CHANGES>
private Deque<Set<String>> referenceStack = new ArrayDeque<Set<String>>();
<CHANGEE>
<CHANGES>
private Map<String, List<Node>> nameMap = Maps.newHashMap();
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
public void enterScope(NodeTraversal t) {
if (t.inGlobalScope()) {
return;
}
referenceStack.push(referencedNames);
referencedNames = Sets.newHashSet();
<CHANGEE>
<CHANGES>
public void exitScope(NodeTraversal t) {
if (t.inGlobalScope()) {
<CHANGEE>
<CHANGES>
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
handleScopeVar(v);
}
<CHANGEE>
<CHANGES>
Set<String> current = referencedNames;
referencedNames = referenceStack.pop();
<CHANGEE>
<CHANGES>
if (!referenceStack.isEmpty()) {
referencedNames.addAll(current);
}
}
<CHANGEE>
<CHANGES>
void handleScopeVar(Var v) {
String name = v.getName();
if (containsSeparator(name)) {
String newName = getOrginalName(name);
<CHANGEE>
<CHANGES>
if (TokenStream.isJSIdentifier(newName) &&
!referencedNames.contains(newName) &&
!newName.equals(ARGUMENTS)) {
referencedNames.remove(name);
<CHANGEE>
<CHANGES>
referencedNames.add(newName);
List<Node> references = nameMap.get(name);
Preconditions.checkState(references!= null);
for (Node n : references) {
Preconditions.checkState(n.getType() == Token.NAME);
n.setString(newName);
}
<CHANGEE>
<CHANGES>
nameMap.remove(name);
<CHANGEE>
<CHANGES>
}
@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node node, Node parent) {
if (t.inGlobalScope()) {
return;
}
if (NodeUtil.isReferenceName(node)) {
String name = node.getString();
<CHANGEE>
<CHANGES>
referencedNames.add(name);
<CHANGEE>
<CHANGES>
if (containsSeparator(name)) {
addCandidateNameReference(name, node);
<CHANGEE>
<CHANGES>
private void addCandidateNameReference(String name, Node n) {
List<Node> nodes = nameMap.get(name);
if (null == nodes) {
nodes = Lists.newLinkedList();
nameMap.put(name, nodes);
}
nodes.add(n);
}
<CHANGEE>
<CHANGES>
if (!name.equals(ARGUMENTS)) {
<CHANGEE>
<CHANGES>
}
declarations.put(name, newName);
<CHANGEE>
<CHANGES>
<CHANGEE>
<CHANGES>
Preconditions.checkState(!name.equals(ARGUMENTS));
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
static boolean isReferenceName(Node n) {
return isName(n) &&!n.getString().isEmpty() &&!isLabelName(n);
}
<CHANGEE>
<FILEE>
<FILEB>
<CHANGES>
<CHANGEE>
<CHANGES>
removeDuplicateDeclarations(root);
<CHANGEE>
<FILEE>
<FILEB>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
<CHANGES>
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
<CHANGEE>
import com.google.javascript.jscomp.Scope.Var;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TokenStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Find all Functions, VARs, and Exception names and make them
* unique. Specifically, it will not modify object properties.
* @author johnlenz@google.com (John Lenz)
* TODO(johnlenz): Try to merge this with the ScopeCreator.
*/
class MakeDeclaredNamesUnique
implements NodeTraversal.ScopedCallback {
<CHANGES>
<CHANGEE>
private Deque<Renamer> nameStack = new ArrayDeque<Renamer>();
private final Renamer rootRenamer;
MakeDeclaredNamesUnique() {
this.rootRenamer = new ContextualRenamer();
}
MakeDeclaredNamesUnique(Renamer renamer) {
this.rootRenamer = renamer;
}
static CompilerPass getContextualRenameInverter(AbstractCompiler compiler) {
return new Contextual<SCANS> * Gets the source node or null if this is an unknown function.
*/
public Node getSource() {
return source;
}
/**
* Sets the source node.
*/
public void setSource(Node source) {
this.source = source;
}
/** Adds a type to the list of subtypes for this type. */
private void addSubType(FunctionType subType) {
if (subTypes == null) {
subTypes = Lists.newArrayList();
}
subTypes.add(subType);
}
/**
* Returns a list of types that are subtypes of this type. This is only valid
* for constructor functions, and may be null. This allows a downward
* traversal of the subtype graph.
*/
public List<FunctionType> getSubTypes() {
return subTypes;
}
@Override
public boolean hasCachedValues() {
return prototype != null || super.hasCachedValues();
}
/**
* Gets the template type name.
*/
public String getTemplateTypeName() {
return templateTypeName;
}
@Override
JSType resolveInternal(ErrorReporter t, StaticScope<JSType> scope) {
call = (ArrowType) safeResolve(call, t, scope);
prototype = (FunctionPrototypeType) safeResolve(prototype, t, scope);
typeOfThis = (ObjectType) safeResolve(typeOfThis, t, scope);
boolean changed = false;
ImmutableList.Builder<ObjectType> resolvedInterfaces =
ImmutableList.builder();
for (ObjectType iface : implementedInterfaces) {
ObjectType resolvedIface = (ObjectType) iface.resolve(t, scope);
resolvedInterfaces.add(resolvedIface);
changed |= (resolvedIface != iface);
}
if (changed) {
implementedInterfaces = resolvedInterfaces.build();
}
if (subTypes != null) {
for (int i = 0; i < subTypes.size(); i++) {
subTypes.set(i, (FunctionType) subTypes.get(i).resolve(t, scope));
}
}
return super.resolveInternal(t, scope);
}
}